mongodb $where with another indexed field - mongodb

Mongodb doc says $where does a collection scan, which is bad, but if I add an indexed field in the query, will that take advantage of indexed speed?
db.users.find({
_id: someMongodbId,
$where: function() { return this.name == 'joe' } // ensure this doc has name "joe"
});
In the example above, there's only 1 query because of _id field, right?

Related

How does mongodb use an index to count documents?

According to docs, db.collection.countDocuments() wraps this:
db.collection.aggregate([
{ $match: <query> },
{ $group: { _id: null, n: { $sum: 1 } } }
])
Even if there is an index, all of the matched docs will be passed into the $group to be counted, no?
If not, how is mongodb able to count the docs without processing all matching docs?
The MongoDB query planner can make some optimizations.
In that sample aggregation, it can see that no fields are required except for the ones referenced in <query>, so it can add an implicit $project stage to select only those fields.
If those fields and the _id are all included in a single index, there is no need to fetch the documents to execute that query, all the necessary information is available from the index.

Mongo Upsert with values of find $in

I have to run mongo updates by querying that the user id is in an array. Is it possible to upsert any values not in the array?
Eg:
db.collection.update({
userId:{
$in:['1','2', '3']
}
},
{$set: {score:30}},
{upsert:true})
If I run this query I get one new doc with _id and score. What I'd like to do is have a new doc for each userId not present in the userId array:
[{userId:1, score:30, _id:...}, {userId:2, score: 30, _id: ...}, ...]
Is this possible in mongo?
No, this cannot be done. The documentation states:
If upsert is true and no document matches the query criteria, update() inserts a single document.

Return fields one level up from subdocument query mongodb

I am trying to return a field one level up in my subdocument query. My schema is:
profile:{
contacts:[{
first_name:'Tom',
last_name:'Smith',
shared:[{
owner_id:'something',
other_data:'something'
}]
},
{
//.... more contacts
}]
}
if I write a query to get a particular contact by matching something in the 'shared' subdocument, I have access to the fields in the subdocument.
My problem is I want to search for contacts based on an owner_id in the shared subdocument, but I want to return the 'first_name' and 'last_name' one level up.
To query the subdocument I would do the following:
db.profile.find({'contacts.shared':{ower_id:'something},{'first_name':1, 'last_name':1}})
Does not return the fields in the parent.
How do you move up a level to get those fields?
try this
db.people.aggregate([
{$unwind:'$profile.contacts'},
{$unwind:'$profile.contacts.shared'},
{$match:{
'profile.contacts.shared.owner_id':"1"}
},{
$group:{
_id:null,
fname:{$first:"$profile.contacts.first_name"},
lname:{$first:"$profile.contacts.last_name"}
}
}
])

MongoDB update collection's data

I try to update an MongoDB data by using this code:
db.medicines.update({"_id":"586a048e34e5c12614a7424a"}, {$set: {amount:'3'}})
but unfortantly the query does not recognize the selector "_id":"586a048e34e5c12614a7424a", even if its exists.
Its succsed when I change the key to another like: name,rate and etc..
there is a special way to use update with _id parameter?
Thanks a head.
_id will be the unique ObjectId that mongodb generates for every document before inserting it. The query dint work because _id is an ObjectId and "586a048e34e5c12614a7424a" is a String. You need to wrap _id with ObjectId().
If you're using mongodb query
db.medicines.update({
"_id": ObjectId("586a048e34e5c12614a7424a")
}, {
$set: {
amount: '3'
}
});
If you are using mongoose. You can use findByIdAndUpdate
db.medicines.findByIdAndUpdate({
"_id": "586a048e34e5c12614a7424a"
}, {
$set: {
amount: '3'
}
});

how to get results from mongoDB where _id is string objectId

in my mongo database _id is string from ObjectId like this:
when I make this query I get results but with wrong sorting
db.collection.find({ _id : {$gt:"57c03e6288579757b5172d51"} });
how to fix that ?
You cannot query by inserting the objectID string with $gt operator.
You will have to create an objectID.
var objID = ObjectId("57c03e6288579757b5172d51");
db.collection.find({ _id : {$gt: objID} });
Documentation