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.
Related
I have a collection that looks like this:
{
"_id" : ObjectId("5e5777b74db43342073051e0"),
"a" : "b"
}
{
"a" : "c",
"_id" : ObjectId("5e5777f24db43342073051e4")
}
And I want to copy the value of each document’s a into a new array field so I end up with this:
{
"_id" : ObjectId("5e5777b74db43342073051e0"),
"a" : "b",
"d": ["b"]
}
{
"_id" : ObjectId("5e5777f24db43342073051e4"),
"a" : "c",
"d": ["c"]
}
I tried this command at the shell:
db.getCollection("C").updateMany({}, {
$set: {
"d.0": "$a"
}
});
But that gave me:
{
"_id" : ObjectId("5e5777b74db43342073051e0"),
"a" : "b",
"d" : {
"0" : "$a"
}
}
{
"_id" : ObjectId("5e5777f24db43342073051e4"),
"a" : "c",
"d" : {
"0" : "$a"
}
}
$$a gave me the same result. How do I write this operation?
In Mongo 4.2 the <update> document can also be an aggregation pipeline. Try this one:
db.getCollection("C").updateMany(
{},
[{
$set: {
"d": ["$a"]
}
}]
)
I have this collection...
> db.banks.find().pretty()
{
"_id" : ObjectId("54f37cbb44aec3b01b7db8f4"),
"name" : "A",
"branches" : [
{
"branch_id" : 8561,
"name" : "X",
},
{
"branch_id" : 8576,
"name" : "Y",
}
]
}
{
"_id" : ObjectId("54f37cbb44aec3b01b7db8f5"),
"name" : "B",
"branches" : [
{
"branch_id" : 3238,
"name" : "Z",
}
]
}
with this command :
db.banks.aggregate({$project{"branches.name":1,"_id":0}});
get this result :
{ "branches" : { { "name" : "X" }, { "name" : "Y" } } }
{ "branches" : { { "name" : "Z" } } }
but; how I get this result?
(In fact, one object and without "branches".)
{{"name" : "X"}, {"name" : "Y"}, {"name" : "Z"}}
very thanks...
One way you could go about this is to do an $unwind first in the aggregation pipeline to get a deconstructed array with a document for each element and then group by the array element $branches.name:
db.banks.aggregate([
{ $unwind: '$branches'},
{
$group: {
_id: {
name: '$branches.name'
}
}
},
{
$project: {
_id: 0,
name: '$_id.name'
}
},
{ $sort : { "name" : 1 } }
])
Outputs:
{
"result" : [
{
"name" : "X"
},
{
"name" : "Y"
},
{
"name" : "Z"
}
],
"ok" : 1
}
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'})
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 }
);
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