Values = new Meteor.Collection("values");
if (Meteor.isServer) {
Meteor.startup(function () {
Meteor.setInterval(function() {
Values.insert({id: Math.random(), name: "value"});
console.log(Values.find({name: "value"}).id);
}, 1000);
});
}
I have that code and I'm trying to add a value to Values every second and find all the values I have and print them every second. However, it is not finding the values I add and is outputting:
I2043-14:21:56.895(0)? undefined
find returns a cursor, which is an object that contains the results of your search (somewhat like an array of results). It does it this way since find can get more than just one result, depending on the selector you passed.
It has a forEach similar to JS that accepts a function and receives the document, the index, and the cursor as parameters.
Values.find({name: "value"}).forEach(function(doc,index,cursor){
console.log(doc.id);
});
Visually, a result of find in your case looks something like:
[
{id: SOME_RANDOM_NUMBER, name: "value"},
{id: SOME_RANDOM_NUMBER, name: "value"},
{id: SOME_RANDOM_NUMBER, name: "value"},
{id: SOME_RANDOM_NUMBER, name: "value"},
]
Related
I want to be able to modify , or add or delete individual source arrays in the eventSources array. But I am not sure how to remove individual event sources. Because they get merged together - how would I remove individual ones?
I add them in this way:
eventSources: [
eventSource1,
holidays,
flagDays,
churchDays
]
They get merged as one array. So I can't get the first array (eventSource1) by doing:
var currentEvents = $('#calendar').fullCalendar('clientEvents');
var eventSource1 = currentEvents[0]; //<-- undefined
I tried adding them wrapped in separate arrays:
eventSources: [
[eventSource1],
[holidays],
[flagDays],
[churchDays]
]
But now they are not loaded into the calendar,the calendar is empty.
In the documentation: removeEventSources it says you are supposed to provide an "optionalSourcesArray" which should contain
"identifier items, which can be either an event source’s
id/Array/URL/Function or the full Event Source Object.".
I can't guess what they mean by it. I use version 3.9.
--------------Update:-----------------
Using below comment I can do:
eventSources: [
{ id: 1,
events: eventSource1
},
{ id: 2,
events: holidays
},
{ id: 3,
events: flagDays
},
{ id: 4,
events: churchDays
}
]
Then I can delete individual event sources - if I want to delete the first three:
$('#calendar').fullCalendar('removeEventSources', [1,2,3] ) ;
The final thing I need is to be able to get an event source array.
I can use the getEventSourceById method:
$('#calendar').fullCalendar( 'getEventSourceById', 4 );
But this gives me a class object - how will I get the event source array?
I have a meteor publication in which I was trying to use .findOne() to access the fields from the mongodb. But as I cannot return .findOne() from a meteor publish, I am now using just .find(). The problem is that it returns a cursor instead of a document so I am not able to read the values inside that cursor in my publish function.
Below is my mongodb query
var question = Question.find({ "_id": quesId },
{ fields: {"pages": 1, "settings.name": 1, "status": 1 }},
{limit: 1});
And I want to use the value of pages that I get from the above query inside the same publish function
you can set an observer on your cursor and get a hook into the results. i do that frequently to transform the result.
e.g. (i am making the assumption that the publish name is "questions")
let cursor = Question.find({ "_id": quesId }, { "pages": 1, "settings.name": 1, "status": 1 }, {limit: 1});
let handle = cursor.observeChanges({
added: (id, fields) => {
// look at fields
this.added('questions', id, fields);
},
changed: (id, fields) => {
// look at fields
this.changed('questions', id, fields);
},
removed: (id) => {
this.removed('questions', id);
}
});
this.ready();
this.onStop(() => {
handle.stop();
});
this will give you a hook into the records that are added at the initial publish, and changed later. call ready() when your publication is ready to be published (you can see the this.ready() in the sample).
As far as I understand your question, you want to access the single document in the cursor without doing a redundant findOne() in your code. You can transform the result into an array with .fetch() on the cursor, get the first entry with [0] and then directly get the pages attribute.
const question = Question.find(quesId,
{ fields: { "pages": 1, "settings.name": 1, "status": 1 }});
const pages = question.fetch()[0].pages;
Note also that when searching on _id you don't have to specify {_id: quesId} in your filter, you can directly use the value you want to search on as the filter parameter, mongo assumes that you're searching on _id. Furthermore the {limit: 1} is redundant since you're searching on a scalar _id value and so you're guaranteed that the cursor length will be one.
I have a current route as follows:
Router.route('/:arg', function(){
this.render('tmpResults', {
data: function(){
return hcDrefs.find({name: {$regex: this.params.query.q}})
}
});
}, {name: 'showSome'});
As you can see, the query is hard coded to really only take a single input (see block below). What I want to do is execute this route where the query object would need to be of a variable form...sometimes I only need a simple query, other times, the query may contain an AND operation. I currently call this route with:
Router.go('showSome', {arg: 1},
{query: '?q=' + e.target.value});
}
...what I want to know is if I can pass some kind of query object to the route somehow, but I haven't seem to hit on a syntax that work....not even sure IF it can work. I have tried some brute force stuff like defining a query object:
query_object = {name: {$regex: pattern}}
and attempting to get it to the router somehow like:
Router.go('showSome', {arg: 1},
{query: query_object});
}
//----------------------------------------------------------
Router.route('/:arg', function(){
this.render('tmpResults', {
data: function(){
return hcDrefs.find(this.params.query.q}})
}
});
}, {name: 'showSome'});
but that seems to be a no go.
What would be a good way to set the data context of a route where the query to yield the data context could be of a variable form? I would think a global object would probably work, but I am curious is there is a more strategic way passing through the router. I am still digging through the iron router docs for something I can hook onto.
There is no client-side POST, so the data you can pass to a client-side route is limited by what you can put into the URL (similar to a GET request). So, no, I don't think there is a more elegant solutions.
I think you have two options:
Stringifying your object into the URL:
Router.go('showSome', {arg: 1},
{query: JSON.stringify(query_object)});
//----------------------------------------------------------
Router.route('/:arg', function(){
this.render('tmpResults', {
data: function(){
return hcDrefs.find(JSON.parse(this.params.query)}})
}
});
}, {name: 'showSome'});
2) use a global or session variable:
Session.set('query', query_object);
Router.go('showSome', {arg: 1});
//----------------------------------------------------------
Router.route('/:arg', function(){
this.render('tmpResults', {
data: function(){
return hcDrefs.find(Session.get('query'))}})
}
});
}, {name: 'showSome'});
I've been struggling with this for a couple of hours and I can't find a good solution so maybe someone can shed a light on this.
I have a simple schema like this:
var groupschema = new SimpleSchema({
name: {
label: 'Name',
type: String
},
description: {
label: 'Description',
type: String
}
}
And I have another one:
var itemschema = new SimpleSchema({
name: {
label: 'Type:',
type: String
},
details: {
label: 'Details',
type: String
},
group: [groupschema] // <--- this is my main interest
}
If I use the above code sample AutoForm will generate an "inner form" which is quite cool actually for some puporse (e.g. for a contact to have an array of adresses or phone numbers) but for me I would like a drop-down select with the name of the group and when I click on the Insert/Update button (depending on the current form) I would like to add the whole group document to the inserted/updated item document as a subdocument.
Something like this will be inserted to the mongodb:
{
_id: the generated mongoid,
name: "This is a type",
details: "There are some thing to know about this type",
group:{
name: "Cool group",
description: "This is a really cool group"
}
}
The actual documents are far more complicated the above example is just an oversimplified version.
I've stopped writing this question yesterday and tried to do my own version.
My - half baked - solution is:
introducing a new field in the schema named groupselect (type string, autoform type: select)
populate it's contents with a Collection.find().map() lookup
groupselect: {
type: String,
label: 'Group',
optional: true,
blackbox: true,
autoform:{
type: "select",
options : function() {
return Issuegroup.find().map(function (c) {
return {label: c.name , value: c._id};
});
}
}
},
using autoform hooks before insert I assign the subdocument to the real fiel group = Group.find({_id:doc.groupselect}) and I remove the helper field from the doc
using the same technique in the before update hook also for an update form
The problem I seem to be unable to solve in a clean way is to set the default value of the helper field 'groupselect' when the update form displays. I've tried the docToForm hooks but no luck.
Isn't this somehow a very common problem? I imagine there has to be a proper solution for this so I bet that I am missing something very obvious and hopefully someone will point it out for me.
Thanks
I am using Simple Schema,collection hooks and Autoform packages in Meteor and I am trying to update a Embedded object in my schema in the after update collection hook. I feel I might doing something silly, but was just unable to solve this problem. I am getting the exeption while saving: Exception while invoking method '/providers/update' Error: 0 must be an integer
My schema:
Schemas.Providers = new SimpleSchema({
email: {
type: String,
label: 'Email Address',
autoValue: function() {
if (this.isInsert || this.isUpdate) {
return Meteor.user().emails[0].address;
}
},
autoform: {
afFieldInput: {
type: 'email'
}
}
},
officelocation: {
type: String,
label: 'Location of Office',
optional:true
},
location: {
type: [LocationSchema],
optional:true
}});
The collection hook that works:
Providers.after.update(function (userId, doc) {
var oldDoc = this.previous;
Providers.direct.update({_id: doc._id},{$set: {location:{
type:'Point',
coordinates:[0,0]
}}});
});
The collection hook that does not work.. Ideally I should not be updating after the collection update, but wanted to make sure this works:
Providers.after.update(function (userId, doc) {
var oldDoc = this.previous;
var array=[];
var iArray=doc.officelocation.split(",");
array.push(Number(iArray[1]));
array.push(Number(iArray[0]))
Providers.direct.update({_id: doc._id},{$set: {location:[{
type:'Point',
coordinates:array
}]}});
});
Looking at what you are trying to store, use parseInt instead of Number that you are using. It will return an integer that mongo can store.
The issue is not with the method that you are using. It is with the way you are storing data in mongo. Show us how your LocationSchema looks like.
Detail:
Mongo uses a different number format that what javascript uses. In javascript, a Number can be an integer, a float, a decimal or anything that you want. Mongo has very strict demands when it comes to integer or floats.
Overall, what it means is that if you want to store an accurate decimal number in mongo (which I suspect what you are trying to do), you have to either store it as a string (you loose the ability to do direct mongo operation such as $inc $gt etc) or divide it into two parts and store separably. The third option is to store it as a float which isn't accurate an is only useful if you want some kind of approximate value.