Mongo find based on value in array of objects - mongodb

the documents looks like :
{
name: 'abc',
types: [
{name:'Large',stock:true},
{name:'XLarge',stock:false},
{name:'XXLarge',stock:true}
]
}
I'm trying to figure out the query to return all documents which are out of stock.
Something like : .find({types:{{$nin:{stock:true}}})
Can I somehow do that?

You can query using positional operator like this:
db.collection.find({'types.stock':{$ne:true}})
$nin operator is used for finding elements not in a particular array. $ne (not equal to) is a much better operation in your case.

Related

what is the proper way to use $nin operator with mongoDB

I want to find entries in my MongoDB collection that match some filters.
Each entry in my mongo collection looks like this data:
{
type: "admin"
senderId: "6131e7c597f50700160703fe"
read_by: [
{
Object_id: 614dbbf83ad51412f16c0757
readerId: "60b968dc5150a20015d6fcae"
}
]
},
{
type: "admin"
senderId: "6131e7c597f50700160703fe"
read_by: [
{}
]
}
What I want to achieve properly, is to filter on the collection and get only the entries that match 'admin' as type and that don't have the current user's ID in the read_by array (that is an array of objects)
I wrote this (and tried some other combinations with errors :) )
but it is not working, I get 0 entries on the end, but I expect to get one of the two as the second have it's read_by array empty.
Thank you very much!
I validated my solution using cloud.mongodb.com interface and the simplest following filter seems to do the job:
{ "read_by.readerId": {$ne:"60b968dc5150a20015d6fcae"}}
Only the record with empty array is being returned.
$nin operator works fine as well but if there is only single value for comparision then $ne should be enough.
{ "read_by.readerId": {$nin: ["60b968dc5150a20015d6fcae"]}}

MongoDB check if value exists within array

I'm using MongoDB inside a twig framework. I'm trying to determine if the user has access to a certain module.
(a part of) my DB entry looks like:
_id: "579b50a4f5092761a20f4e71",
approvedModules: [
"examplemodule",
"examplemodule1",
"examplemodule2",
"examplemodule3"
],
My code looks like:
session.get('__AUTH_USER').find({ approvedModules : { '$in' : ["examplemodule"]}}, { '$exists' : true })
(the standard functions have to be in quotes).
I keeps returning false. I can only return the value if I use session.get('__AUTH_USER').approvedModules.0
I don't want to include the .0 because that might change.
What am I doing wrong?
Thanks in advance!
What am I doing wrong?
Many things. The worst one is using queries to database inside a template, but it is another problem.
You misunderstood purpose of the $in operator, which is used to match a field in the database to any element of array in the query.
To match any element of array in the collection to a single value you can do simple $eq:
session.get('__AUTH_USER').find({ approvedModules : "examplemodule"})
When you are using $in operator, you need to have 2 input arguments, the first one is the value for which you are checking the array, and the second one should be the array itself.
So, your bson element should look like this:
isModuleInArray : { '$in' : ["examplemodule","$approvedModules"] }

MongoDB filter by array of objectIds

I have a document that has a array of ObjectIDs for reference. That array is not an associative array, it's just the ObjectIDS:
{
...
"tags" : [
ObjectId("54744662ae8a0be602568c4f")
]
}
Now I'm trying to filter based on that array, like this:
db.expenses.find({
tags:{
$elemMatch:{ObjectId("547469bb0bde915a05f74299")}
}
})
I know that the projection on the $elemMatch is wrong, but I just don't know how to do it, and Google isn't helping must because most of the examples are for and array of json objects with defined properties.
Does anyone know how to do this?
If I got your problem correctly, this would be the answer
db.expenses.find(
{
tags: {$in : [ObjectId("54744662ae8a0be602568c4f")]}
})

Mongodb projection returning a given position

I am trying to do something as simple as return a subarray of a document. So my query is:
db.mydocs.findOne({_id:ObjectId("af7a85f758e338d762000012")},{'house.0.room.4.windows':1});
I want to return only that value. But I get an empty structure. I know I could do it with $slice. But as far as I know, I can't do it for subarrays. I mean: {'house':{'$slice':0}} would work. But I don't know how to get house 0 and room 4.
You'll have to use chained $slice operators for this to work:
db.mydocs.findOne(
{_id:ObjectId("af7a85f758e338d762000012")},
{"house" : {$slice : [0,1]}, // house.0
"house.room" :{$slice : [3,1]}, // house.0.room.4
"house.room.windows" : 1}); // house.0.room.4.windows
The resulting document will look like this, i.e. the arrays are still arrays (which is helpful when mapping to strongly typed languages):
house : [ { room : [ { windows : foo } ] } ]
from the documentation:
Tip: MongoDB does not support projections of portions of arrays except when using the $elemMatch and $slice projection operators.
P.S: I find it irritating that house and room are arrays, but have singular names, esp. because windows is plural.

MongoDB : use $ positional operator for querying

I have a collection with entries that look like :
{
"userid": 1,
"contents": [
{ "tag": "whatever", "value": 100 },
{"tag": "whatever2", "value": 110 }
]
}
I'd like to be able to query on that collection and returning only one part of the array : the one matching the query. I'm trying to use the $ positional operator to do so but it hasn't worked so far.
Here is more precisely what I'd like to do :
collection.find({'contents.tag':"whatever"},{'contents.$.value':1})
As a result I expect sth with only the value corresponding to the entry in the array that matched query, which is 100 in this case.
Do you know what's wrong ? I was thinking that maybe the $ operator can only be used for update and not for querying. Anyone in the know ?
Thanks !
Yes, you are correct - the positional operator is used for updating an object.
The solution for now would be to return the array an pull the field out in your application.
There is an open enhancement request for this feature (in queries):
https://jira.mongodb.org/browse/SERVER-828
For more information on the positional operator, see:
http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator
What you are looking for is the $elemMatch operator.
It might be an overkill, but I guess you can use map-reduce for this.
first, pre-filter with a query, emit all array elements in map, filter the ones that do not match either in emit or in reduce. If you don't set out everything will happen in RAM.
If you have to run those kinds of queries often, it might be worthwhile to duplicate the data.
Nevertheless, I hope the SERVER-828 will be implemented soon!
Create a query with $in instead and add your equal value to the array, this can solve your issue
$users_array = array(xxxxxxxx,yyyyyy);
$user = Db::find('fb_users', array(
'facebook_id' => array(
'$in' => array($users_array)
)
));