I have two objects:
{
genre: ['music', 'movie']
}
and
{
genre: ['movie', 'music']
}
and my query is:
db.test.find({genre :{ $elemMatch:{ $in : ['movie']}}})
and it only gives me the second object. Why? I want to get all the docs that contain a specific genre in their arrays no matter where in the array. How can I do this?
You need neither $elemMatch nor $in in this case. A simple field:value will match documents where field is an array and any one of the values in that array is value. That means
db.test.find({genre :'movie'});
will suffice.
The array query operators are required in more complex situations.
$in is needed when you have a list of possible values and want documents where any of them is found (so db.test.find({genre : { $in:['movie']} }); would work, but would be needlessly convoluted)
$all works like $in but requires that all provided elements are in the array
$elemMatch is a bit more complex. It is required when you want to use multiple operator-conditions (like $gt or $lt) but want only those documents where one array entry matches all the conditions. Without the $elemMatch operator, you get results where each condition is met by at least one array entry, but not necessarily all by the same entry.
Remember db.test.find() in general returns you cursor object. You can access all doc as follows:
entry = db.test.find({genre :{ $elemMatch:{ $in : ['movie']}}})
for doc in entry:
print(doc)
Related
I have a column like
A. 'col' : [
'5ed3ede8844f0f351100000c',
'5ed3f117a844e0471100000d'
]
or some other case data
B. 'col' : [
'5ed3ede8844f0f351100000c'
]
C. 'col' : [
'5ed3ede8844f0f351100000c',
'5ed3f117a844e0471100000d',
'5ed3f18132f50c491100000e'
]
How to get A record that match exactly an array but regardless of the order of elements in the array with one query
Example
.find({'col': ['5ed3ede8844f0f351100000c','5ed3f117a844e0471100000d']})
or .find({'col': ['5ed3f117a844e0471100000d', '5ed3ede8844f0f351100000c']})
How to do that thanks
In order to find a record that match exactly a specified array without taking into consideration the order of the elements within the array, you can combine the $size and the $all query operators.
So for example:
.find({ 'col': { "$size": 2, "$all": ['5ed3f117a844e0471100000d', '5ed3ede8844f0f351100000c'] } })
Note: you can also use the $in query operator, but for your case it looks like the $all is a better fit
I want to search list of collections from mongoDB have all the keywords of given string.
For e.g.
I have a collection
{
"id":1
"text":"go for shopping",
"description":"you can visit this branch as well"
}
{
"id":2
"text":"check exiting discount",
"description":"We have various discount options"
}
Now, If I will pass string like "I want to go for shopping" w.r.t. text field in find query of mongoDB. Then I should get first collection as output because text field value "go for shopping" exists in the input string passed in find query.
This can be achieved through $text operator in MongoDB. But you have to createIndex on the "text" field in your database.(or whichever filed you want to be matched, I would suggest you rename it in your db to avoid confusion)
db.yourCollectionName.createIndex({"text":"text"})
The first field here is the "text" field in your database, and the second one is the mongo operator.
Then you can pass any query like,
db.yourCollectionName.find({$text: {$search: "I want to go for shopping"}})
The "$text" here is the mongo operator.
This would return all documents which have any of the keywords above.
Maybe you can read more around this and improvise and modify.
Ref: MongoDb $text
You can do so through regular expression. MongoDb provides the provision of matching strings through regex patterns.
In your case you could do something like:
db.yourCollectionName.find({text:{$regex:"go for shopping" }})
This will return you all the documents having the phrase "go for shopping" in the text field.
Ref: MongoDb Regex
I have created a text index on the num field in the collection. Now while passing the string to search from the text index, I need to use a regex which has to be passed as a string to the $search variable.
My current query works fine but it doesn't work when I add a regex to it.
Current Query:
db.collection.find({$text:{$search:"1234 6789"}},{'id':1})
I need to add a regex/like query to the $search to make it something like
db.collection.find({$text:{$search:"/1234/ /6789/"}},{'id':1})
where I get all the values from the database that contain a pattern like "1234" OR "6789".
I did try the query but it gives me a $search needs a String error:
db.collection.find({$text:{$search:/1234/}},{'id':1})
To achieve this you should use the $regex MongoDB operator:
// Without options
db.collection.find({num: /1234|5678/i});
// Separate options property
db.collection.find({num: {$regex: /1234|5678/, $options: 'i'}});
To add multiple terms in the regex, use the | operator
$regex docs and examples
Edit:
For querying records using an array of values the $in operator can be used:
$in docs and examples
I want to remove a specific element from array stored in mongodb document.
I am using this:
model.registerCompany.findOneAndUpdate({companyKey:"a key"},
{$pop:{onlineEmployees:"John"}},
function(err,doc){
if(!err)
console.log("Online list modified: ",doc);
else
console.log("Online list modified error :",err);
});
But I am not sure if the $pop removes the specific element "John" from array(onlineEmployees) or just pop out the last element from it.
Am i doing it right or there is another way to do it.?
I think i got the answer .. $pull is used for this purpose as explained here in the link:
http://docs.mongodb.org/manual/reference/operator/pull/#_S_pull
The $pop operator will remove first or last element of the array, which may not necessarily be the right one.
If you want a specific element, you can $pull the item with defined criteria:
model.registerCompany.findOneAndUpdate({companyKey:"a key"},
{$pull:{onlineEmployees:"John"}},
You have to make sure the value in the array is unique, for $pull removes every element matching the name 'John'.
If identical values exist in the array, you need to use $unset and $ positional operator to set the target element value to null(unfortunately $unset won't remove elements) and then use $pull to remove the element with null value. To do that, you have to make sure valid value can not be null. In that case, the code could be like:
model.registerCompany.findOneAndUpdate({companyKey:"a key", onlineEmployees:"John"},{ $unset: { "onlineEmployees.$" : '' } } )
model.registerCompany.findOneAndUpdate({companyKey:"a key"},{ $pull: { "onlineEmployees" : null } } )
In my database I have documents which all contain the property foo. For each value of foo I have a function that either returns true or false. How can I query for all the documents for which the value of foo makes the function return true?
If you need to check if your string field's value is one of several, you need the $in modifier.
db.collection.find( { field : { $in : array } } );
It works fast and uses index (if possible).
If your field is an array and you pass a string, use this syntax.
db.collection.find({array_field : string_value});
It will check every element in the array and, if any of them matches your string, it will return the document.
You could use $where.
Example:
db.myCollection.find( { $where: "this.a > 3" });
db.myCollection.find( "this.a > 3" );
db.myCollection.find( { $where: function() { return this.a > 3;}});
Note, this is run in Javascript. This means two things.
You can put arbitrary Javacript into $where expression (the function form).
It'll be significantly slower than regular queries.
It really depends on what the function is and how you are using it. Is the function constant for any given record? Is it even a function you can evaluate on the database server? ...
In the extreme, if you need to check this value often, you might, for example, create a field that exists only when f(foo) is true and then create a sparse index on that field.
$where may well be the solution you are looking for, but depending on the access patterns there may be a better solution.