MongoDB Aggregate search with comma separated string list in array - arrays

I have a MongoDB question. I have a search in an aggregation with $match.
Search should check an array if one of the values matches a value of the array inside the documents.
As an example:
var stringList = 'general,online,offline'; //--> should check each value of this list
and two documents as an example
{
"_id" : ObjectId("5e8f3a64ec717a0013d2f1f9"),
"category" : [
"general",
"online",
"internal",
"miscellaneous"
]},
{
"_id" : ObjectId("5e8f3afeec717a0013d2f1fa"),
"category" : [
"offline"
]
}
I´ve tried a lot but I don´t found out how it is possible to check each value of the string list with each value in the category array. My example should show both documents, but if I use $in I don´t get any result.
What I tried is:
Split the list by comma and map
use of $elemMatch
use if $in
use combination of $elemMatch and $in
I hope I could explain my problem with my aggregation.
Thx everyone for his help.

You should be able to split the string on , with .split function, then pass this in to a $in query.
var stringList = 'general,online,offline';
db.documents.find( { "category" : { $in : stringList.split(",") } } );
{ "_id" : ObjectId("5e8f3a64ec717a0013d2f1f9"), "category" : [ "general", "online", "internal", "miscellaneous" ] }
{ "_id" : ObjectId("5e8f3afeec717a0013d2f1fa"), "category" : [ "offline" ] }
You can also do this in a $match in an aggregation query.
> db.documents.aggregate([
{ $match : { category: { $in : stringList.split(",") } }}
])

Here is an example, where we can search the array name from by using the regex method in the query.
var x = ["sai","test","jacob","justin"],
regex = x.join("|");
db.documents.find({
"firstName": {
"$regex": regex,
"$options": "i"
}
});

Related

MongoDB split string and Update

I have document structure like this:
{
"_id" : ObjectId("5a3a77d9d274eb44bc85d7c8"),
"b_id" : 3,
"b_display_tag" : "Veg Curry, Non Veg Curry"
}
I am able to get the first element from the string in b_display_tag using split and aggregate query:
db.blogs.aggregate([
{$project: {"b_display_tag": {$arrayElemAt:[{$split: ["$b_display_tag" , ","]}, 0]}}}
])
Result:
/* 1 */
{
"_id" : ObjectId("5a3a77d9d274eb44bc85d7c8"),
"b_display_tag" : "Veg Curry"
}
How can I update b_display_tag in the whole document with the first element from comma separated string?
Use below query to update b_display_tag. It will split b_tags using separator(') and update b_display_tag with first index.
db.blogs.find().forEach(function (blog)
{
if (blog.b_tags)
{
blog.b_display_tag=blog.b_tags.split(',');
blog.b_display_tag=blog.b_display_tag[0];
db.blogs.save(blog);
}
});
You can use $out in the aggregation pipeline to write it into a new collection, since here we need to update the existing collection blogs use the same collection name in $out.
db.blogs.aggregate([
{$project:
{
_id:1,
b_id:1,
b_display_tag:{$arrayElemAt:[{$split:["$b_display_tag", ","]}, 0]}
}
},
{$out:"blogs"}
]);

Mongodb query array

I need to get all documents that match an array of objects or an object with many fields.
Example 1 (array of objects)
If the document match the country_code than he must have one of postal_codes too
var locations = [
{
country_code : 'IT',
postal_codes : [21052, 21053, 21054, 21055]
},
{
country_code : 'GER',
postal_codes : [41052, 41053, 41054, 41055]
}
]
Example 2 (object with fields)
If the document match the key than it must have one of the values of that key
var location = {
'IT' : [21052, 21053, 21054, 21055],
'GER' : [41052, 41053, 41054, 41055]
}
I like the first type of document to match(array of objects) but how can i use to get all documents that match?
The documents to find have this structure:
{
"_id" : ObjectId("587f6f57ed6b9df409db7370"),
"description" : "Test description",
"address" : {
"postal_code" : "21052",
"country_code" : "IT"
}
}
You can use $in to find such collections.
db.collection_name.find(
{ address.postal_code: { $in: [your values] } },
)
Check this link for querying child objects.
Check this link for mongoDB $in
One way is to use the $or operator. This will help you limit the combinations of country_code and postal_code.
Your query should look something like this.
db.locations.find({
$or: [{
"country_code": "IT",
"postal_code": {
$in: [21052, 21053, 21054, 21055]
}
}, {
"country_code": "GER",
"postal_code": {
$in: [41052, 41053, 41054, 41055]
}
}]
})

How to retrieve a specific field from a subdocument array with mongoose

I'm trying to get a specific field from a subdocument array
I'm not gonna include any of the fields in the parent doc
Here is the sample document
{
"_id" : ObjectId("5409dd36b71997726532012d"),
"hierarchies" : [
{
"rank" : 1,
"_id" : ObjectId("5409df85b719977265320137"),
"name" : "CTO",
"userId" : [
ObjectId("53a47a639c52c9d83a2d71db")
]
}
]
}
I would like to return the rank of the hierarchy if the a userId is in the userId array
here's what I have so far in my query
collectionName.find({{hierarchies:
{$elemMatch : {userId: ObjectId("53a47a639c52c9d83a2d71db")}}}
, "hierarchies.$.rank", function(err,data){}
so far it returns the entire object in the hierarchies array I want, but I would like to limit it to just the rank property of the object.
The projection available to .find() queries generally in MongoDB does not do this sort of projection for internal elements of an array. All you can generally do is return the "matched" element of the array entirely.
For what you want, you use the aggregation framework instead, which gives you more control over matching and projection:
Model.aggregate([
{ "$match": {
"hierarchies.userId": ObjectId("53a47a639c52c9d83a2d71db")
}},
{ "$unwind": "$hierarchies" },
{ "$match": {
"hierarchies.userId": ObjectId("53a47a639c52c9d83a2d71db")
}},
{ "$project": {
"rank": "$hierarchies.rank"
}}
],function(err,result) {
})
That basically matches the documents, filters the array content of the document to just the match and then projects only the required field.

MongoDB search using $in array not working

I'm using MongoDB shell version: 2.4.8, and would simply like to know why a nested array search doesn't work quite as expected.
Assume we have 2 document collections, (a) Users:
{
"_id" : ObjectId("u1"),
"username" : "user1",
"org_ids" : [
ObjectId("o1"),
ObjectId("o2")
]
}
{
"_id" : ObjectId("u2"),
"username" : "user2",
"org_ids" : [
ObjectId("o1")
]
}
and (b) Organisations:
{
"_id" : ObjectId("o1"),
"name" : "Org 1"
}
{
"_id" : "ObjectId("o2"),
"name" : "Org 2"
}
Collections have indexes defined for
Users._id, Users.org_id, Organisations._id
I would like to find all Organisations a specific user is a member of.
I've tried this:
> myUser = db.Users.find( { _id: ObjectId("u1") })
> db.Organisations.find( { _id : { $in : [myUser.org_ids] }})
yet it yields nothing as a result. I've also tried this:
> myUser = db.Users.find( { _id: ObjectId("u1") })
> db.Organisations.find( { _id : { $in : myUser.org_ids }})
but it outputs the error:
error: { "$err" : "invalid query", "code" : 12580 }
(which basically says you need to pass $in an array) ... but that's what I thought I was doing originally ? baffled.
Any ideas what I'm doing wrong?
db.collection.find() returns a cursor - according to documentation. Then myUser.org_ids is undefined, but $in field must be an array. Let's see the solution!
_id is unique in a collection. So you can do findOne:
myUser = db.Users.findOne( { _id: ObjectId("u1") })
db.Organisations.find( { _id : { $in : myUser.org_ids }})
If you are searching for a non-unique field you can use toArray:
myUsers = db.Users.find( { username: /^user/ }).toArray()
Then myUsers will be an array of objects matching to the query.

mongodb : search an array of hashes

db.test.insert({_id:1,communications:[{type:'sms'}]})
db.test.find()
{ "_id" : 1, "communications" : [ { "type" : "sms" } ] }
Ok, its inserted
db.test.find({'communications':{type:'sms'}})
{ "_id" : 1, "communications" : [ { "type" : "sms" } ] }
Ok, I can find it if its an exact match
db.test.update({_id:1}, {communications:[{type:'sms',call_id:9878}]}
Now I updated it such that the hash nested in the array has two keys
.test.update({_id:1}, {communications:[{type:'sms',call_id:9878}]})
But I can't find it bc the hash is not the exact match! NOOOOO!
db.test.find({'communications':{type:'sms'}}).count()
=>0
So, how can I do a search like that where I want to match on one of the keys in a hash in an array?
If I've understood correctly (no guarantees I have!), then I think what you are looking for is the dot notation.
db.test.find({'communications.type':'sms'}).count()
Here's the reference on MongoDb.org with all the examples.

Resources