Mongodb array structure - mongodb

Theres something here I can't quite figure out.
When I attempt to query an object with several fields I yield no results. The object structure looks like this:
{
"_id" : ObjectId("4d8b55f017a7303b0b000000"),
"title" : "Apollo",
"body" : "A spaceflight mission to the moon",
"tags" : [ [ "moon", "space", "nasa", "mission" ] ]
}
This is my query:
db.test.find({ tags: { $all: ['moon', 'mission'] } })
However I do get result by creating a new object with a single field:
{
"_id" : ObjectId("4d8b9e5935037b3c8228709c"),
"tags" : [ "apple", "banana", "pear" ]
}
... with the same query as the one above.
['tags'] isn't nested inside any other array, so why does it not return my search queries? Please enlighten me.
Sincerely,
Why

Why are you using a nested array
"tags" : [ [ "moon", "space", "nasa", "mission" ] ]
here?
This does not make any sense.

db.test.find({ tags: { $all: [ ['moon', 'mission'] ] } })

Related

Is there a way to query for dict of arrays of array in MongoDB

My mongo db collection contains the structure as :
{
"_id" : ObjectId("5889ce0d2e9bfa938c49208d"),
"filewise_word_freq" : {
"33236365" : [
[
"cluster",
4
],
[
"question",
2
],
[
"differ",
2
],[
"come",
1
]
],
"33204685" : [
[
"node",
6
],
[
"space",
4
],
[
"would",
3
],[
"templat",
1
]
]
},
"file_root" : "socialcast",
"main_cluster_name" : "node",
"most_common_words" : [
[
"node",
16
],
[
"cluster",
7
],
[
"n't",
3
]
]
}
I want to search for a value "node" inside the arrays of arrays of the filename (in my case its "33236365","33204685" and so on...) of the dict filewise_word_freq.
And if the value("node") is present inside any one of the array of arrays of the filename(33204685), then should return the filename(33204685).
I tried from this link of stackoverflow :
enter link description here
I tried to execute for my use case it didn't work. And above all this I didn't no how to return only the filename rather the entire object or document.
db.frequencydist.find({"file_root":'socialcast',"main_cluster_name":"node","filewise_word_freq":{$elemMatch:{$elemMatch:{$elemMatch:{$in:["node"]}}}}}).pretty().
It returned nothing.
Kindly help me.
the data model you have chosen has made it extremely difficult to either query or even for aggregation. I would suggest to revise your document model. However I think you can use $where
db.collection.find({"file_root": 'socialcast',
"main_cluster_name": "node", $where : "for(var i in this.filewise_word_freq){for(var j in this.filewise_word_freq[i]){if(this.filewise_word_freq[i][j].indexOf("node")>=0){return true}}}"})
yes, this will return you the whole document and from your application you might need to filter the files name out.
you might also want to see map-reduce functionality, though that's not recommended.
One other way is to do it through functions, functions runs on mongo server and are saved in a special collection.
Still going back to the db model, do revise it if that's a possibility. maybe something like
{
"_id" : ObjectId("5889ce0d2e9bfa938c49208d"),
"filewise_word_freq" : [
{
"fileName":"33236365",
"word_counts" : {
"cluster":4,
"question":2,
"differ":2,
"come":1
}
},
{
"fileName":"33204685",
"word_counts" : {
"node":6,
"space":4,
"would":3,
"template":1
}
}
]
"file_root" : "socialcast",
"main_cluster_name" : "node",
"most_common_words" : [
{
"node":16
},
{
"cluster":7
},
{
"n't":3
}
]
}
It would be a lot easier to run aggregation on these.
For this model, the aggregation would be something like
db.collection.aggregate([
{$unwind : "$filewise_word_freq"},
{$match : {'filewise_word_freq.word_counts.node' : {$gte : 0}}},
{$group :{_id: 1, fileNames : {$addToSet : "$filewise_word_freq.fileName"}}},
{$project :{ _id:0}}
])
this will provide you a single document with a single field fileNames with list of all the filename
{
fileNames : ["33204685"]
}
You can try something like this. This will match the node as part of the query and returns filewise_word_freq.33204685 as part of the projection.
db.collection.find({
"file_root": 'socialcast',
"main_cluster_name": "node",
"filewise_word_freq.33204685": {
$elemMatch: {
$elemMatch: {
$in: ["node"]
}
}
}
}, {
"filewise_word_freq.33204685": 1
}).pretty();

How to count and paginate subdocument which is an object in mongodb

I have data saved in the following:
{
"_id" : ObjectId("57723b5e009793e8f3cfd1d7"),
"room" : "1003",
"inout" : {
"1" : [
"i1654",
"o1656",
"i1706",
"o1707",
],
"2" : [
"i1655",
"o1656",
"i1715",
"o1715"
],
"3" : [
"i1801"
]
}
}
how to count and paginate the subdocument "inout" which is an object?
thanks!!!
Actually, there is a small modification required in your JSON. The "inout" should be an array to use the below solution.
"$unwind" can be used here.
Modified JSON to define "inout" as array rather than Object:-
db.rooms_second.insertOne({
"_id" : ObjectId("57723b5e009793e8f3cfd1d7"),
"room" : "1003",
"inout" : [
{"1" : [
"i1654",
"o1656",
"i1706",
"o1707",
]},
{"2" : [
"i1655",
"o1656",
"i1715",
"o1715"
]},
{"3" : [
"i1801"
]}
]
});
Mongodb Query:-
In the resultset, the below query will give you one record for each element in the "inout" array.
db.rooms_second.aggregate([ { $unwind: "$inout" } ])
The pagination can be done based on the driver and API that you are using (i.e. MongoDB Java Driver etc.).

Updating an object in a nested array in Mongoose

Given the following schema
{
"_id" : ObjectId("55e0ecfa422d86f0a3b37b90"),
"username" : "Michael",
"hostedEvents" : [
{ "_id" : "1", "usersApplied" : [ ] }
],
"joinedEvents" : [
{ "confirmed" : false }
]
}
And I am trying to push into the usersApplied array the string "Lisa"
Right now I have a mongodb command that works but I want to do this in mongoose:
db.users.update({username:'Michael', "hostedEvents._id": "1"},
{$addToSet: {"hostedEvents.$.usersApplied": {"username":"Lisa"}}});
I tried to do it in mongoose this way:
Users.update({username:'Michael', "hostedEvents._id": "1"},
{$addToSet: {"hostedEvents.$.usersApplied": {"username":"Lisa"}}});
I am trying to follow the recommendation made here
I think you should use $push instead
Users.update({username:'Michael', "hostedEvents._id": "1"},
{$push: {"hostedEvents.$.usersApplied": {"username":"Lisa"}}});
That should work.

Removing a (sub) array in MongoDB using $pull

So..I'm evaluating Mongodb for managing a bit of my JSON back end. I'm totally new to it and I had one problem that was just messy to do in code, so I thought — heck — let me check out to see if it's time to finally start using Mongo
I have a data structure that is approximately like this:
[
{
"_id" : ObjectId("526f59ee82f2e293f9833c54"),
"humans" : [
{
"serviceUsers" : [
{
"foo1" : "bar2",
"foo2" : "bar3"
},
{
"foo1" : "baz2",
"foo2" : "baz3"
}
]
}
]
}
]
And now I want to remove any serviceUsers array elements that have "foo1" equal to "baz2" so that ideally I would end up with this:
[
{
"_id" : ObjectId("526f59ee82f2e293f9833c54"),
"humans" : [
{
"serviceUsers" : [
{
"foo1" : "bar2",
"foo2" : "bar3"
},
]
}
]
}
]
I figured that $pull was the place to start. And I tried a bunch of contortions. If I'm in collection mytests, I tried
db.mytests.update({"humans.serviceUsers.foo1":"baz2"}, {$pull:{"humans.serviceUsers" : {"foo1":"baz2"}}}, {multi: true})
Which to my admittedly naive eye, seems like it should follow the $pull syntax:
db.collection.update( { field: <query> }, { $pull: { field: <query> } } );
Mongo doesn't complain. But it doesn't change the collection in any way, either.
I also tried
db.mytests.update({}, {$pull:{"humans.serviceUsers" : {"foo1":"baz2"}}}, {multi: true})
Which also failed.
Any suggestions are greatly appreciated.
Thus humans is also array, you should use positional $ operator to access serviceUsers array of matched humans element:
db.mytests.update({ "humans.serviceUsers.foo1" : "baz2" },
{ $pull: { "humans.$.serviceUsers" : { "foo1": "baz2" }}});

MongoDB query help: $elemMatch in nested objects

> db.test.insert({"a" : { "b" : { "c" : { "d1" : [ "e1" ],
"d2" : [ "e2" ],
"d3" : [ "e3", "e4" ],
"d4" : [ "e5", "e6" ] } } } })
> db.test.find({'a.b.c' : {$exists : true}})
{ "_id" : ObjectId("4daf2ccd697ebaacb10976ec"), "a" : { "b" : { "c" : { "d1" : [ "e1" ], "d2" : [ "e2" ], "d3" : [ "e3", "e4" ], "d4" : [ "e5", "e6" ] } } } }
But none of these work:
> db.test.find({'a.b': "c"})
> db.test.find({'a.b': {$elemMatch : {"c" : {$exists: true}}}})
> db.test.find({'a.b': {$elemMatch : {$elemMatch : {$all : ["e1"] }}}})
Suppose I don't know what the values of c and d1...d4 are. Is there a generic way to search the nested-objects' structure for particular values?
I thought that was what $elemMatch was for.
Thank you.
I thought that was what $elemMatch was for...
From the docs: Using the $elemMatch query operator, you can match an entire document within an array.
This does not sounds like what you're looking for.
Is there a generic way to search the nested-objects' structure for particular values?
It sounds like you want to search "everything in object 'c' for an instance of 'e1'".
MongoDB supports two related features, but the features not quite what you're looking for.
Reach into objects, dot notation: db.test.find({'a.b.c.d1' : 'e1'})
Read through arrays: `db.test.find({'a.b.c.d4' : 'e5'})
It sounds like you're looking for the ability to do both at the same time. You want to "reach into objects" and "read through arrays" in the same query.
Unfortunately, I do not know of such a feature. You may want to file a feature request for this.
I believe the query you're looking for is
db.test.find({ 'a.b.c': { '$exists': true } });
To your credit, you were very close!