Similar to this question
Barrowing the data set, I have something similar to this:
{
'user_id':'{1231mjnD-32JIjn-3213}',
'name':'John',
'campaigns':
[
{
'campaign_id':3221,
'start_date':'12-01-2012',
},
{
'campaign_id':3222,
'start_date':'13-01-2012',
}
]
}
And I want to add a new key in the campaigns like so:
{
'user_id':'{1231mjnD-32JIjn-3213}',
'name':'John',
'campaigns':
[
{
'campaign_id':3221,
'start_date':'12-01-2012',
'worker_id': '00000'
},
{
'campaign_id':3222,
'start_date':'13-01-2012',
'worker_id': '00000'
}
]
}
How to insert/update a new key into an array of objects?
I want to add a new key into every object inside the array with a default value of 00000.
I have tried:
db.test.update({}, {$set: {'campaigns.worker_id': 00000}}, true, true)
db.test.update({}, {$set: {campaigns: {worker_id': 00000}}}, true, true)
Any suggestions?
I'm supposing that this operation will occur once, so you can use a script to handle it:
var docs = db.test.find();
for(var i in docs) {
var document = docs[i];
for(var j in document.campaigns) {
var campaign = document.campaigns[j];
campaign.worker_id = '00000';
}
db.test.save(document);
}
The script will iterate over all documents in your collection then over all campaigns in each document, setting the *worker_id* property.
At the end, each document is persisted.
db.test.update({}, {$set: {'campaigns.0.worker_id': 00000}}, true, true
this will update 0 element.
if you want to add a new key into every object inside the array you should use:
$unwind
example:
{
title : "this is my title" ,
author : "bob" ,
posted : new Date() ,
pageViews : 5 ,
tags : [ "fun" , "good" , "fun" ] ,
comments : [
{ author :"joe" , text : "this is cool" } ,
{ author :"sam" , text : "this is bad" }
],
other : { foo : 5 }
}
unwinding tags
db.article.aggregate(
{ $project : {
author : 1 ,
title : 1 ,
tags : 1
}},
{ $unwind : "$tags" }
);
result:
{
"result" : [
{
"_id" : ObjectId("4e6e4ef557b77501a49233f6"),
"title" : "this is my title",
"author" : "bob",
"tags" : "fun"
},
{
"_id" : ObjectId("4e6e4ef557b77501a49233f6"),
"title" : "this is my title",
"author" : "bob",
"tags" : "good"
},
{
"_id" : ObjectId("4e6e4ef557b77501a49233f6"),
"title" : "this is my title",
"author" : "bob",
"tags" : "fun"
}
],
"OK" : 1
}
After you could write simple updaiting query.
Related
I have two collections.
1.Equipment
db.getCollection("Equipment").find({
$and: [
{ $where: 'this._id.length <= 7' },
{ "model": "A505"}
]})
{
"_id" : "1234567",
"locationId" : "DATALOAD",
"model" : "A505",
"subscriberId" : "",
"status" : "Stock",
"headendNumber" : "4"
}
{
"_id" : "P13050I",
"locationId" : "1423110302801",
"model" : "A505",
"subscriberId" : "37",
"status" : "Stock",
"headendNumber" : "4"
}
I will get more than 100 documents (rows) Equipment collection.
2.Subscriber
db.getCollection('Subscriber').find({})
{
"_id" : "5622351",
"equipment" : [
"0018015094E6",
"1234567",
"ADFB70878422",
"M10610TCB052",
"MA1113FHQ151"
]
}
{
"_id" : "490001508063",
"equipment" : [
"17616644510288",
"P13050I",
"M91416EA4251",
"128552270280560"
]
}
In the Subscriber collection, I need to remove (get all the id from Equipment collection loop it) only the matches equipment field.
Forex from the above result, I need to remove only "1234567", and "P13050I"
Expected output.
db.getCollection('Subscriber').find({})
{
"_id" : "5622351",
"equipment" : [
"0018015094E6",
"ADFB70878422",
"M10610TCB052",
"MA1113FHQ151"
]
}
{
"_id" : "490001508063",
"equipment" : [
"17616644510288",
"M91416EA4251",
"128552270280560"
]
}
Please help me, anyone.
You can use the following to update records.
Let's find records which need to deleted and store them in array
var equipments = [];
db.getCollection("Equipment").find({ $and: [
{ $where: 'this._id.length <= 7' },
{ "model": "A505"}
]}).forEach(function(item) => {
equipments.push(item._id)
})
Now, iterate over records of the second collection and update if required.
db.getCollection('Subscriber').find({}).forEach(function(document) => {
var filtered = document.equiment.filter(id => equipments.indexOf(id) < 0);
if(filtered.length < document.equipment.length){
db.getCollection('Subscriber').update({"_id": document.id }, { $set: {'equipment': filtered}})
}
})
.filter(id => equipments.indexOf(id) < 0) will keep entries which is not present in initially populated array equipments and it will persist if there is any change.
I have such Article-documents:
{
"_id" : "rNiwdR8tFwbTdr2oX",
"createdAt" : ISODate("2018-08-25T12:23:25.797Z"),
"title" : "Happy",
"lines" : [
{
"id" : "5efa6ad451048a0a1807916c",
"text" : "Test 1",
"align" : "left",
"indent" : 0
},
{
"id" : "ae644f39553d46f85c6e1be9",
"text" : "Test 2"
},
{
"id" : "829f874878dfd0b47e9441c2",
"text" : "Test 3"
},
{
"id" : "d0a46ef175351ae1dec70b9a",
"text" : "Test 4"
},
{
"id" : "9bbc8c8d01bc7029220bed3f",
"text" : "Test 5"
},
{
"id" : "6b5c02996a830f807e4d8e35",
"text" : "Test 6",
"indent" : 0
}
]
}
I need to update some Lines.
For example I have array with ids of the line which must be updated.
let lineIds = [
"5efa6ad451048a0a1807916c",
"829f874878dfd0b47e9441c2",
"6b5c02996a830f807e4d8e35"
];
So I try to update attributes "attr" for the "lines" and I do following:
'articles.updateLines': function (articleId, lineIds, attr, value) {
return Articles.update({
'_id': articleId,
'lines.id': { $in: lineIds }
},
{
$set: {
['lines.$.' + attr]: value
}
},
{ multi: true }
);
}
The problem is that just the first line (with id="5efa6ad451048a0a1807916c") is updated.
Any ideas? Thanks! :)
You can use $[]. This will works only MongoDB version 3.6 and above.
Refer link :
https://docs.mongodb.com/manual/reference/operator/update/positional-all/
You can also see this stackoverflow question reference:
How to add new key value or change the key's value inside a nested array in MongoDB?
You can convert below query in your function
db.col.update(
{ '_id':"rNiwdR8tFwbTdr2oX", },
{ $set: { "lines.$[elem].text" : "hello" } },
{ arrayFilters: [ { "elem.id": { $in: lineIds } } ],
multi: true
})
'lines.id': { $in: lineIds }
This won't work, because lines is an array.
What I understand from your question, you can prepare a new array with proper processing and replace the lines array with the new one. Here is an idea how to do this:
'articles.updateLines': function (articleId, lineIds, attr, value) {
let lines = Articles.findOne(articleId).lines;
// prepare a new array with right elements
let newArray = [];
for(let i=0; i<lines.length; i++){
if(lineIds.includes(lines[i].id)){
newArray.push(value)
}
else newArray.push(lines[i])
}
return Articles.update({
'_id': articleId,
},
{
$set: {
lines: newArray
}
}
);
}
I have a collection with multiple documents which follow this structure:
{
"_id" : {
"oid" : XXX
},
"name" : "Name",
"videos" [
{
"id" : 1,
"thumbnail" : "thumbnail.jpg",
"name" : "Name here"
},
{
"id" : 2,
"thumbnail" : "thumbnail.jpg",
"name" : "Name here"
},
{
"id" : 3,
"thumbnail" : "thumbnail.jpg",
"name" : "Name here"
}
]
}
I want to find and update the a thumbnail of a video, of which I only know the id, but not which document it is in.
This is what I've tried so far, but it's not working properly. All the examples I found relied on knowing the document id, and the array position of the object to update. I also found that doing a query like this found the document okay, but set the whole document as the new thumbnail!
db.collection(COLLECTION-NAME, function(err, collection){
collection.update(
{ 'videos.id' : 2 },
{ $set: { thumbnail: "newThumbnail.jpg" } },
function(err, result){
if (!err){
console.log('saved', result)
} else {
console.log('error', err);
}
}
);
});
Use the $ positional operator to update the value of the thumbnail field within the embedded document having the id of 2:
db.collection.update(
{ "videos.id": 2 },
{ "$set": { "videos.$.thumbnail" : "newThumbnail.jpg" } }
)
I have a collection in which element has a list of objects. I would like to use $orderBy on a specific field on the first element of a list of objects that each document has.
For example:
each document represents a user, and each user has a list of sessions. I would like to sort the users on the date stored in the first session of the list.
Maybe something like { $orderby: { "sessions[0].timestamp" : 1 } } ?
Is this possible?
The operation you ask for is a simple one with .sort(). Perhaps you are not aware of the usage of "dot notation" with MongoDB
With the following documents as a minimal example:
{
"name" : "Fred",
"sessions" : [ { "timestamp" : ISODate("2014-06-05T10:38:24.371Z") } ]
}
{
"name" : "Barney",
"sessions" : [ { "timestamp" : ISODate("2014-06-05T10:38:34.557Z") } ]
}
Issue the following query:
db.users.find({},{ _id: 0}).sort({ "sessions.0.timestamp": -1 })
And get the ordered result by the first item of the array, timestamp field:
{
"name" : "Barney",
"sessions" : [ { "timestamp" : ISODate("2014-06-05T10:38:34.557Z") } ]
}
{
"name" : "Fred",
"sessions" : [ { "timestamp" : ISODate("2014-06-05T10:38:24.371Z") } ]
}
This is the first of 7 test/example documents, in collection "SoManySins."
{
"_id" : ObjectId("51671bb6a6a02d7812000018"),
"Treats" : "Sin1 = Gluttony",
"Sin1" : "Gluttony",
"Favourited" : "YES",
"RecentActivity" : "YES",
"GoAgain?" : "YeaSure."
}
I would like to be able to query to retrieve any info in any position,
just by referring to the position. The following document,
{
"_id" : ObjectId("51671bb6a6a02d7812000018"),
"Sin1" : "Gluttony",
"?????????" : "??????",
"RecentActivity" : "YES",
"GoAgain?" : "YeaSure."
}
One could retrieve whatever might be in the 3rd key~value
pair. Why should one have to know ahead of time what the
data is, in the key? If one has the same structure for the
collection, who needs to know? This way, you can get
double the efficiency? Like having a whole lot of mailboxes,
and your app's users supply the key and the value; your app
just queries the dbs' documents' arrays' positions.
Clara? finally? I hope?
The sample document you've provided is not saved as an array in BSON:
{
"_id" : ObjectId("51671bb6a6a02d7812000018"),
"Sin1" : "Gluttony",
"?????????" : "??????",
"RecentActivity" : "YES",
"GoAgain?" : "YeaSure."
}
Depending on the MongoDB driver you are using, the fields here are typically represented in your application code as an associative array or hash. These data structures are not order-preserving so you cannot assume that the 3rd field in a given document will correspond to the same field in another document (or even that the same field ordering will be consistent on multiple fetches). You need to reference the field by name.
If you instead use an array for your fields, you can refer by position or select a subset of the array using the $slice projection.
Example document with an array of fields:
{
"_id" : ObjectId("51671bb6a6a02d7812000018"),
"fields": [
{ "Sin1" : "Gluttony" },
{ "?????????" : "??????" },
{ "RecentActivity" : "YES" },
{ "GoAgain?" : "YeaSure." }
]
}
.. and query to find the second element of the fields array (a $slice with skip 1, limit 1):
db.SoManySins.find({}, { fields: { $slice: [1,1]} })
{
"_id" : ObjectId("51671bb6a6a02d7812000018"),
"fields" : [
{
"?????????" : "??????"
}
]
}
This is one way to Query and get back data when you may not
know what the data is, but you know the structure of the data:
examples in Mongo Shell, and in PHP
// the basics, setup:
$dbhost = 'localhost'; $dbname = 'test';
$m = new Mongo("mongodb://$dbhost");
$db = $m->$dbname;
$CursorFerWrites = $db->NEWthang;
// defining a set of data, creating a document with PHP:
$TheFieldGenerator = array( 'FieldxExp' => array(
array('Doc1 K1'=>'Val A1','Doc1 K2'=>'ValA2','Doc1 K3'=>'Val A3'),
array('Doc2 K1'=>'V1','Doc2 K2'=>'V2','Doc2 K3'=>'V3' ) ) ) ;
// then write it to MongoDB:
$CursorFerWrites->save($TheFieldGenerator);
NOTE : In the Shell : This produces the same Document:
> db.NEWthang.insert({"FieldxExp" : [
{"Doc1 K1":"Val A1","Doc1 K2":"Val A2","Doc1 K3":"Val A3"},
{"Doc2 K1":"V1", "Doc2 K2":"V2","Doc2 K3":"V3"}
]
})
#
Now, some mongodb Shell syntax:
> db.NEWthang.find().pretty()
{
"_id" : ObjectId("516c4053baa133464d36e836"),
"FieldxExp" : [
{
"Doc1 K1" : "Val A1",
"Doc1 K2" : "Val A2",
"Doc1 K3" : "Val A3"
},
{
"Doc2 K1" : "V1",
"Doc2 K2" : "V2",
"Doc2 K3" : "V3"
}
]
}
> db.NEWthang.find({}, { "FieldxExp" : { $slice: [1,1]} } ).pretty()
{
"_id" : ObjectId("516c4053baa133464d36e836"),
"FieldxExp" : [
{
"Doc2 K1" : "V1",
"Doc2 K2" : "V2",
"Doc2 K3" : "V3"
}
]
}
> db.NEWthang.find({}, { "FieldxExp" : { $slice: [0,1]} } ).pretty()
{
"_id" : ObjectId("516c4053baa133464d36e836"),
"FieldxExp" : [
{
"Doc1 K1" : "Val A1",
"Doc1 K2" : "Val A2",
"Doc1 K3" : "Val A3"
}
]
}
Finally, how about write the Query in some PHP ::
// these will be for building the MongoCursor:
$myEmptyArray = array();
$TheProjectionCriteria = array('FieldxExp'=> array('$slice' => array(1,1)));
// which gets set up here:
$CursorNEWthang1 = new MongoCollection($db, 'NEWthang');
// and now ready to make the Query/read:
$ReadomgomgPls=$CursorNEWthang1->find($myEmptyArray,$TheProjectionCriteria);
and the second document will be printed out:
foreach ($ReadomgomgPls as $somekey=>$AxMongoDBxDocFromCollection) {
var_dump($AxMongoDBxDocFromCollection);echo '<br />';
}
Hope this is helpful for a few folks.