MongoDB: check if nested key value pair exists - mongodb

If got the following database structure:
{ "_id" : "rv8MgKMB9qvrcoruW", "object" : "M5ZMiaqPQYP6Pv45y", "matches" : { "mbGLv9hiJJeyEcSoK" : "1", "hTcs5PYp5bXruZSTL" : "1" } }
{ "_id" : "2jksvGbg7fkguECRB", "object" : "M5ZMiaqPQYP6Pv45y", "matches" : { "mbGLv9hiJJeyEcSoK" : "2", "hTcs5PYp5bXruZSTL" : "2" } }
{ "_id" : "a5Ea5evtXkYrcjtLa", "object" : "M5ZMiaqPQYP6Pv45y", "matches" : { "JZKoX3B8gqiwotphb" : "3", "hTcs5PYp5bXruZSTL" : "3" } }
{ "_id" : "RsLhwDS5ERYxERAjX", "object" : "M5ZMiaqPQYP6Pv45y", "matches" : { "mbGLv9hiJJeyEcSoK" : "4", "JZKoX3B8gqiwotphb" : "4" } }
and i like to get the data set with a specific object and a specific key value pair in matches.
so e.g.: I like to get the dataset for: "object" : "M5ZMiaqPQYP6Pv45y" AND where is existing a DICTIONARY set "JZKoX3B8gqiwotphb" : "3".
So in this case the output should be:
{ "_id" : "a5Ea5evtXkYrcjtLa", "object" : "M5ZMiaqPQYP6Pv45y", "matches" : { "JZKoX3B8gqiwotphb" : "3", "hTcs5PYp5bXruZSTL" : "3" } }
I've tried hundreds of combinations and I am currently stuck with:
db.Matches.find ({ object: 'M5ZMiaqPQYP6Pv45y', matches: { mbGLv9hiJJeyEcSoK: { '$exists': true, $in: '3' } } })

Use dot notation to access field of subdocument:
db.Matches.find({object: 'M5ZMiaqPQYP6Pv45y', 'matches.JZKoX3B8gqiwotphb': '3'})

Related

MongoDB - query for a nested item inside a collection

i have a mongodb collection "result" with data like
{ "_id" : {
"user" : "Howard",
"friend" : "Sita"
},
"value" : {
"mutualFriend" :[ "Hanks", "Bikash", "Shyam", "Bakshi" ]
}
}
{ "_id" : {
"user" : "Shiva",
"friend" : "Tom"
},
"value" : {
"friendList" :[ "Hanks", " Tom", " Karma", " Hari", " Dinesh" ]
}
}
{ "_id" : {
"user" : "Hari",
"friend" : "Shiva"
},
"value" : {
"mutualFriend" :[ "Tom", "Karma", "Dinesh" ]
}
}
Now, here i want to query whole Document having value.mutualFriend. how can i get the result?
Expected Output
{ "_id" : {
"user" : "Howard",
"friend" : "Sita"
},
"value" : {
"mutualFriend" :[ "Hanks", "Bikash", "Shyam", "Bakshi" ]
}
}
{ "_id" : {
"user" : "Hari",
"friend" : "Shiva"
},
"value" : {
"mutualFriend" :[ "Tom", "Karma", "Dinesh" ]
}
}
i have large number of document in MongoDB collection, containing value.friendList and value.mutualFriend and then i want to find only documents with value.mutualFriend
db.collection.find({"value.mutualFriend.0" : { $exists : true }})
Its just make sure that the 0th element exists. you can customize your query over various array length.

MongoDB adding new field to the sub document

I have mongodb document like below.
{
"_id" : ObjectId("57616e718ed5a017089143f2"),
"subitems" : {
"1" : "a",
"2" : "b"
}
}
I was trying to add new fields to "subitems" field.
db.items.update({ "_id" : ObjectId("57616e718ed5a017089143f2") }, { $set: { subitems: { 3: "c" } } })
Instead of updating the field, its overwriting it like
{
"_id" : ObjectId("57616e718ed5a017089143f2"),
"subitems" : {
"3" : "c"
}
}
How do i achieve result
{
"_id" : ObjectId("57616e718ed5a017089143f2"),
"subitems" : {
"1" : "a",
"2" : "b",
"3" : "c"
}
}
Use the dot notation to add the field to an embedded document:
db.items.update(
{ "_id" : ObjectId("57616e718ed5a017089143f2") },
{ "$set": { "subitems.3": "c" } }
)
More from the documentation.

MongodDB retrieve a subdocument by the property name

My document looks like:
{ "entity_id" : 2,
"features" :
[
{ "10" : "name" },
{ "20" : "description" },
... ,
{ "90" : "availability" }
]
}
I would like to, knowing 2 things: the value of "entity_id" (2), and the value of the property in one of the elements of the "features" array, to retrieve only the subdocument
{ "20" : "description" }
in one query. Many thanks!
If you want to get only a part of the whole document, use so called Projection operators
See examples below:
> db.collection.find().pretty()
{
"_id" : ObjectId("52e861617acb7ce761e64a93"),
"entity_id" : 2,
"features" : [
{
"10" : "name"
},
{
"20" : "description"
},
{
"90" : "availability"
}
]
}
Projection operators are specified in find() like here:
> db.collection.find({},{ features : { $elemMatch : { 20 : { $exists: true } }}}).pretty()
{
"_id" : ObjectId("52e861617acb7ce761e64a93"),
"features" : [
{
"20" : "description"
}
]
}
> db.collection.find({},{ entity_id : 1, features : { $elemMatch : { 20 : { $exists: true } }}}).pretty()
{
"_id" : ObjectId("52e861617acb7ce761e64a93"),
"entity_id" : 2,
"features" : [
{
"20" : "description"
}
]
}
> db.collection.find({},{ _id : 0, entity_id : 1, features : { $elemMatch : { 20 : { $exists: true } }}}).pretty()
{ "entity_id" : 2, "features" : [ { "20" : "description" } ] }
$elemMatch for projection is available in MongoDB since version 2.2.
Hope it solves your problem.

MongoDB $elemMatch display issue

Listed are the following sample documents in a test collection
My requirement is to extract *only" two fields
"host.name" and "host.config.storageDevice.scsiLun.lunType" matching the condition that "host.config.storageDevice.scsiLun.lunType" : "cdrom1" and "host.name" : "on-xxx"
Like I mentioned above , I only want attribute "lunType" to be displayed in the array and not "a" or "b"
I attempted to use both $elemMatch and $projection and it always seems to return all the attributes of array "lunType" ... Am I missing anything here
Attempted in reference to documentation
http://docs.mongodb.org/manual/reference/projection/elemMatch/
Query
db.test.find({"host.config.storageDevice.scsiLun": { $elemMatch: { "lunType" : "cdrom1" } } },{ "host.name" : 1, "host.config.storageDevice.scsiLun.$" : 1})
db.test.find({"host.config.storageDevice.scsiLun.lunType" : "cdrom1" },{ "host.name" : 1, "host.config.storageDevice.scsiLun.$" : 1})
Documents in collection
{
"_id" : ObjectId("51d57f3ad4ebc6c87962d4c0"),
"host" : {
"name" : "on-xxx",
"config" : {
"storageDevice" : {
"scsiLun" : [
{
"a" : "1",
"lunType" : "cdrom1"
},
{
"a" : "2",
"lunType" : "disk2"
},
{
"a" : "3",
"lunType" : "disk3"
}
]
}
}
}
}
,
{
"_id" : ObjectId("51d57f59d4ebc6c87962d4c1"),
"host" : {
"name" : "on-yyy",
"config" : {
"storageDevice" : {
"scsiLun" : [
{
"a" : "4",
"lunType" : "cdrom4"
},
{
"a" : "5",
"lunType" : "disk5"
},
{
"a" : "6",
"lunType" : "disk6"
}
]
}
}
}
}
,
{
"_id" : ObjectId("51d57f74d4ebc6c87962d4c2"),
"host" : {
"name" : "on-zzz",
"config" : {
"storageDevice" : {
"scsiLun" : [
{
"a" : "7",
"lunType" : "cdrom11"
},
{
"a" : "8",
"lunType" : "disk22"
},
{
"a" : "9",
"lunType" : "disk32"
}
]
}
}
}
}
All $elemMatch does is to return the first element of the array that matches a criteria, but it will give you the entire element, that is both "a" and "lunType" properties.
What might get the desired result with aggregation using $unwind to break down the array, then $match to filter and $project to show only the "lunType" field.
I didn't test the query but it should look like this:
db.test.aggregate(
{ $unwind : "$host.config.storageDevice.scsiLun" },
{ $match : { host.name : "on-xxx" ,
host.config.storageDevice.scsiLun.lunType : "cdrom1" } },
{ $project : {
_id : 0 ,
host.config.storageDevice.scsiLun.lunType : 1 }
);

In MongoDb, how to apply sort internal fields present in document?

My document looks like this
{
field1: somevalue,
name:xtz
nested_documents: [ // array of nested document
{ x:"1", y:"2" }, // first nested document
{ x:"2", y:"3" }, // second nested document
{ x:"-1", y:"3" }, // second nested document
// ...many more nested documents
]
}
How one can sort the data present in nested_documents?
Expected answer is shown below:
nested_documents: [ { x:"-1", y:"3" },{ x:"1", y:"2" },{ x:"2", y:"3" }]
To do this you would have to use the aggregation framework
db.test.aggregate([{$unwind:'$nested_documents'},{$sort:{'nested_documents.x':
1}}])
this returns
"result" : [
{
"_id" : ObjectId("5139ba3dcd4e11c83f4cea12"),
"field1" : "somevalue",
"name" : "xtz",
"nested_documents" : {
"x" : "-1",
"y" : "3"
}
},
{
"_id" : ObjectId("5139ba3dcd4e11c83f4cea12"),
"field1" : "somevalue",
"name" : "xtz",
"nested_documents" : {
"x" : "1",
"y" : "2"
}
},
{
"_id" : ObjectId("5139ba3dcd4e11c83f4cea12"),
"field1" : "somevalue",
"name" : "xtz",
"nested_documents" : {
"x" : "2",
"y" : "3"
}
}
],
"ok" : 1
Hope this helps