Find Value in Meteor Mongo - javascript

I am new to web programming and have recently been playing around with Meteor and MongoDB.
I have a form which sends data to mongo and using the query below have retrieved the most recently entered value:
database.findOne({}, {sort: {'timeStamp' : -1}, limit:1})
Which is cool however, I only want the value of a specific variable not the entire entry so I can use that variable with calculations elsewhere.
Does anyone have an pro tips? Should I use distinct()?
Thanks!

If you are looking to retrieve a field out of the returned document, you can specify as much using the fields option:
database.findOne({}, {sort: {'timeStamp' : -1}, limit:1, fields: {'myField': 1, _id: 0})
That will retrieve an object in format like this:
{'myField': 'value of myField'}
So if you want to interact directly with that you can access it like so:
var myVar = database.findOne({}, {sort: {'timeStamp' : -1}, limit:1, fields: {'myField': 1, _id: 0}).myField
As a more concrete example, I have a user database with username, name, _id, etc., and if I just want to store a user's name in another variable, I can do so like this:
> a = Meteor.users.findOne({}, {fields: {name: 1, _id: 0}}).name;
> a
<- "Bob" // returned "Bob"
Note that if you want to pull the data for a specific ID or other selector, you'll need to fill that in in the selector:
database.findOne({_id: "myId"}, ...)
See the Meteor Mongo.Collection.find documentation for more information.

Related

MongoDB > Can I upsertMany using instance data in the query

I'm currently attempting to synchronise data from an external source, into a Mongo database. The data comes in, as an array, and I'd like to BULK insert or update ("upsert") the data, depending on whether a record with a matching customid already exists.
var data = [{
customid: '123',
name: 'Bob',
occupation: 'Builder'
}]
db.foobar.insertMany(data)
Insert is fine, but now (on subsequent synchronisations), I would like to insert/update the following (sample) data, not knowing if the customid exists... is there any way to do this as a bulk operation? e.g.
var newdata = [{
customid: '123',
name: 'Bob',
occupation: 'Nightclub Bouncer'
}]
db.foobar.updateMany({ customid: $instance.customid }, newdata, { upsert: true })
... or is the only way, to manually iterate over the records and run an update(..)?
I've found a compromise, using bulkWrite and multiple updateOne statements. If anyone has a better solution, please don't hesitate to post it.
https://stackoverflow.com/a/47832754/782034

I am unable to retrieve data from my mongodb collection and show it to my html page [duplicate]

I have a publication that should return me all users matching an _id array. here it the query:
Meteor.users.find({
'_id': { $in: myArray}},{
'profile.name':1,
'profile.description':1,
'profile.picture':1,
'profile.website':1,
'profile.country':1}
);
When I run it in Robomongo (the mongo browser), it works. But my publication only returns undefined. when I console.log(myArray); in the publication, I get something like this ['FZ78Pr82JPz66Gc3p']. This is what I paste in my working Robomongo query.
Alternative question: how can I have a better feedback(log) from the Collection.find() result?
It looks like you are trying to specify fields in your find, which you can do like this:
var options = {
fields: {
'profile.name': 1,
'profile.description': 1,
'profile.picture': 1,
'profile.website': 1,
'profile.country': 1
}
};
Meteor.users.find({_id: {$in: myArray}}, options);
However, if this is being used in a publish function, I strongly recommend using only top-level fields like so:
Meteor.users.find({_id: {$in: myArray}}, {fields: {profile: 1}});
For more details on why, please see this question.
For your second question, you can view the documents returned by a cursor by calling fetch on it. For example:
console.log(Posts.find({_id: {$in: postIds}}).fetch());

Write an object containing an array of objects to a mongo database in Meteor

In my user collection, I have an object that contains an array of contacts.
The object definition is below.
How can this entire object, with the full array of contacts, be written to the user database in Meteor from the server, ideally in a single command?
I have spent considerable time reading the mongo docs and meteor docs, but can't get this to work.
I have also tried a large number of different commands and approaches using both the whole object and iterating through the component parts to try to achieve this, unsuccessfully. Here is an (unsuccessful) example that attempts to write the entire contacts object using $set:
Meteor.users.update({ _id: this.userId }, {$set: { 'Contacts': contacts}});
Thank you.
Object definition (this is a field within the user collection):
"Contacts" : {
"contactInfo" : [
{
"phoneMobile" : "1234567890",
"lastName" : "Johnny"
"firstName" : "Appleseed"
}
]
}
This update should absolutely work. What I suspect is happening is that you're not publishing the Contacts data back to the client because Meteor doesn't publish every key in the current user document automatically. So your update is working and saving data to mongo but you're not seeing it back on the client. You can check this by doing meteor mongo on the command line then inspecting the user document in question.
Try:
server:
Meteor.publish('me',function(){
if (this.userId) return Meteor.users.find(this.userId, { fields: { profile: 1, Contacts: 1 }});
this.ready();
});
client:
Meteor.subscribe('me');
The command above is correct. The issue is schema verification. Simple Schema was defeating the ability to write to the database while running 'in the background'. It doesn't produce an error, it just fails to produce the expected outcome.

Using mongojs and node.js, how to find documents using multiple attributes as criteria

I am trying to use the find method to return documents that meet multiple criteria like so:
db.issues.find({ 'title.name': name, 'title.year': year, 'title.publisher': publisher }, function(err, issues) { ...
I get an empty array back as a result.
If I try the same query directly in the mongodb console, I get the results back as expected.
In mongojs, I am able to retrieve results if I only supply one attribute, like so:
db.issues.find({ 'title.name': name }, function(err, issues) { ...
So, how do I perform a search using multiple attributes? Do I need to use a different method?
UPDATED 2/2/2014 7:56
The issue schema is as follows:
{
title: { name: 'Some title name', year: 1999, publisher: 'Some publisher' },
number: "122",
variant: null,
print: "1",
year: "1999",
certification: { type: "Some certification", grade: 10 },
url: "http://www.someurl.com",
sales: []
}
There is no difference in how mongojs handles queries as it's intention is to mimic ( somewhat ) the behavior of the mongo shell.
Are you sure your criteria actually returns something? As it stands you possibly have an issue there. If you still cannot diagnose this, post up the result you expect to get and some of your schema as an edit. Don't forget to check your var's that numbers aren't strings and vice versa.

fetchRelated not fetching related

Been trying to get this up and running for a while now.
Basically i have a rest api as backend that returns json, all fine.
The problem i have is with backbone-relational. I'm sure i've just got something
wrong but i've been searching the nets for a while and couldn't find anything to help.
I'm trying to get a has many relationship between the model "Profession" and "Weapon".
Here's my code for that:
Profession = Backbone.RelationalModel.extend({
urlRoot: '../api/professions',
relations: [{
type: Backbone.HasMany,
key: 'weapons',
relatedModel: 'Weapon',
collectionType: 'Weapons',
reverseRelation: {
key: 'profession',
includeInJSON: 'id',
keySource: 'profession_id'
}
}]
});
Weapon = Backbone.RelationalModel.extend({
urlRoot: '../api/weapons'
});
Weapons = Backbone.Collection.extend({
model: Weapon,
url: function(models){
return '../api/weapons';
}
});
And a call to those api endpoints returns:
{name: "Profession1", id: 1}
[{name: "Weapon1", profession_id: 1}, {name: "Weapon2", profession_id: 1}]
So, if i understand correctly a profession.fetchRelated('weapons') should send an httprequest to the url for the weapons collection and pull the object which have a profession_id of 1. But nothing happens when i run profession.fetchRelated('weapons')
So, if i understand correctly a profession.fetchRelated('weapons') should send an httprequest to the url for the weapons collection and pull the object which have a profession_id of 1. But nothing happens when i run profession.fetchRelated('weapons')
This is not how I understand Backbone-relational to work - with the caveat that I'm working with an older version, and have not yet investigated the latest versions.
From my understanding, Backbone-relational wants data that looks different from your API responses.
I think that Backbone-relational wants references to nested models in the parent model response, either fully nested:
{
name: "Profession1",
id: 1,
weapons: [
{name: "Weapon1", profession_id: 1},
{name: "Weapon2", profession_id: 1}
]
}
In which case, it will fully populate the nested models.
Or, as references:
{
name: "Profession1",
id: 1,
weapons: ['weapon1','weapon2']
}
In which case Backbone-relational will stash the related keys internally, but present an empty collection. You would then use fetchRelated to fetch the full data for the related models:
assassin.fetchRelated('weapons')
Which make a request for weapons with id 'weapon1' and 'weapon2', either as individual requests, or if your API accepts a set request, a single request, expecting a response something like:
{id: 'weapon1', name: "Weapon1", profession_id: 1}
I don't, off the top of my head, know if there's a quick, built-in way to work with your API responses, other then to write a custom function.
To add to what Edward wrote, here's how you can get fetchRelated to work. First, as Edward claimed, fetchRelated will return nothing if your API already nests the data in the JSON response. So, if in Django-Tastypie you have your resource set up to use full=True:
movies = fields.ToManyField('movie.api.MovieResource', 'user', full=True)
then something like,
myuser.fetchRelated("movies")
will return nothing because the related data will already be included in the JSON response. But where fetch related is particularly useful is when you are attempting to do some lazy loading. So, if you have full=False in your Django-Tastypie field, and your JSON response only includes the id's and resource URI to that entry, you can use fetchRelated to actually populate that data.
myuser = new User({id: 1})
myuser.fetch()
myuser.fetchRelated("movies")
And now you have access to the related movies collection. If you're also using the Tastypie-Backbone plugin, you don't need to worry about constructing a special URL return statement in the Collection. It does it all for you using the tastypie select syntax of /2;3;7

Categories