mongoDB update unset multiple object item within array - mongodb

i want to unset multiple object within array .. this is my db data
{
"_id" : ObjectId("5440e390fb038d3062000001"),
"firstname" : "demo2",
"contacts" : [
{
"contactId" : "544372d5f9ae85d0589d2b71",
"displayname" : "demo1",
"accounts" : {
"00e12ed769eb19239e218355cbe3c24f" : {
"type" : "mobile",
"userId" : "123456789",
"status" : 0,
}
}
},
{
"contactId" : "544372e4f9ae85d0589d2b72",
"displayname" : "demo2",
"accounts" : {
"00e12ed769eb19239e218355cbe3c24f" : {
"type" : "mobile",
"userId" : "123456789",
"status" : 0,
}
}
}
],
}
i used this db query but its updating only one record
db.users.update({'contacts.accounts.00e12ed769eb19239e218355cbe3c24f.userId':'123456789'},
{$unset:{'contacts.$.accounts.00e12ed769eb19239e218355cbe3c24f':''}},{multi:true})
Its updating only one but i want to update multiple items...

Just wrap your update statements in while like:
while (db.users.update({
'contacts.accounts.00e12ed769eb19239e218355cbe3c24f.userId' : '123456789'
}, {
$unset : {
'contacts.$.accounts.00e12ed769eb19239e218355cbe3c24f' : ''
}
}, {
multi : true
}).nMidified);

db.users.find({'contacts.accounts.00e12ed769eb19239e218355cbe3c24f.userId':'123456789'}).forEach(function(item)
{
var contacts = item.contacts;
for(var i = 0; i < contacts.length; i++)
{
var contact = contacts[i];
delete contact.accounts['00e12ed769eb19239e218355cbe3c24f'];
}
// db.users.save(item);
// use update() instead of save(
db.users.update({'contacts.accounts.00e12ed769eb19239e218355cbe3c24f.userId':'123456789'}, item);
})

Related

need to filter query to get selected object in mongodb

I have the below document.
I want to return "employeedata" containing only those array objects (family, academic etc.) for which status is "current"
{
"_id" : ObjectId("5a1fe7ed1e9fdd17285ac13f"),
"createdby" : "admin",
"details" : [
{
"_id" : ObjectId("5a1fe81f1e9fdd17285ac14a"),
"employeedata" : {
"createddate" : "2017-11-30T11:13:57.290Z",
"family" : [
{
"status" : "current",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac153")
}
],
"academic" : [
{
"status" : "archive",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac159")
},
{
"status" : "current",
"_id" : ObjectId("5a1fe8a71e9fdd17285ac15d")
}
],
"company" : [
{
"status" : "archive",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac150")
},
{
"status" : "current",
"_id" : ObjectId("5a1fe88e1e9fdd17285ac15c")
}
],
"other" : [
{
"status" : "current",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac154")
}
]
}
}
]
"confirmed" : true,
}
You can try following to filter the object as it is an complex object we will have to loop through the complete object and modify it at run time.
var data = JSON.parse('{"_id":"5a1fe7ed1e9fdd17285ac13f","createdby":"admin","details":[{"_id":"5a1fe81f1e9fdd17285ac14a","employeedata":{"createddate":"2017-11-30T11:13:57.290Z","family":[{"status":"current","_id":"5a1fe81f1e9fdd17285ac153"}],"academic":[{"status":"archive","_id":"5a1fe81f1e9fdd17285ac159"},{"status":"current","_id":"5a1fe8a71e9fdd17285ac15d"}],"company":[{"status":"archive","_id":"5a1fe81f1e9fdd17285ac150"},{"status":"current","_id":"5a1fe88e1e9fdd17285ac15c"}],"other":[{"status":"current","_id":"5a1fe81f1e9fdd17285ac154"}]}}]}');
function createObject() {
for (var obj in data.details[0].employeedata) {
if (Array.isArray(data.details[0].employeedata[obj])) {
data.details[0].employeedata[obj].filter(function (value, index) {
if (value.status !== 'current') {
//return value;
data.details[0].employeedata[obj].splice(index, 1);
}
})
}
}
}

Query to convert DBRef to Embedded Documents

I have collection like this :
{
"_id" : ObjectId("59edc30b7d1e1f025f78aaac"),
"_class" : "xyz",
"name" : "Test Segment 7",
"attributes" : [
{
"attributeName" : "Country",
"includedAttributes" : [
{
"$ref" : "attribute",
"$id" : ObjectId("59ddffe8d1f2e34eb9d32f36")
}
]
}
]
}
I want a query to convert includedAttributes to it's equivalent attribute object.
Here is the solution that works for me :
db.collection1.find({}).forEach(function(row){
row.attributes.forEach(function(rAttribute){
if(rAttribute.includedAttributes != undefined){
var embededAttributeArray = [];
rAttribute.includedAttributes.forEach(function(iAttr){
var embeddedAttribute = db.getCollection('attribute').find({"_id":iAttr.$id}).toArray()[0];
embededAttributeArray.push(embeddedAttribute);
});
if(embededAttributeArray != undefined){
rAttribute.includedAttributes.length = 0;
for(var i=0;i<embededAttributeArray.length;i++) {
rAttribute.includedAttributes.push(embededAttributeArray[i])
}
db.collection1.save(row);
}
};
});
});

MongoDB 3.2 Update Field name in embedded array

Im trying to do a i migration in my MongoDB. I have updated a Field from Content -> StringContent. Now I want to update all records that exists with the new Field name.
This is how a document looks like.
{
"_id" : "c4af0b19-4c78-4e58-bbe5-ac9e5cce2c3f",
"Type" : "Onboarding",
"Cards" : [
{
"_id" : LUUID("3f328a1c-658d-ee4e-8f06-561760eb5be5"),
"Width" : 1,
"Title" : "",
"Type" : "Freetext",
"Description" : "",
"Content" : "This is a test" // -> "StringContent" : "This is a Test"
},
{
"_id" : LUUID("2f328a1c-658d-ee4e-8f06-561760eb5be5"),
"Width" : 1,
"Title" : "",
"Type" : "Freetext",
"Description" : "",
"Content" : "This is another test" //-> "StringContent" : "This is another Test"
}
],
"DocumentType" : "Template",
"History" : [
{
"Date" : ISODate("2017-07-13T12:03:01.620Z"),
"ByUserId" : LUUID("4ecaa6ca-2ce6-f84c-81f3-28f8f0256e6e")
}
],
"Name" : "Default Template"
}
I have created this script:
var bulk = db.getCollection('OnboardingPortal').initializeOrderedBulkOp(),
count = 0;
db.getCollection('OnboardingPortal').find({"DocumentType": "Template"}).
forEach(function(doc) {
doc.Cards.forEach(function(card) {
if(card.hasOwnProperty("Content")){
print(card);
bulk.find({"_id": doc._id, "Cards._id": card._id}).update(
{
$set: {"Cards.$.StringContent": card.Content}
});
bulk.find({"_id": doc._id, "Cards._id": card._id}).update(
{
$unset: {"Cards.$.Content": 1}
});
count += 2;
if(count % 500 == 0) {
bulk.execute();
bulk = db.getCollection('OnboardingPortal').initializeOrderedBulkOp();
}
}
});
});
if ( count % 500 !== 0 ){
bulk.execute();
}
This Does not update anything, but if I change bulk.operations -> to explicit set index on array like this, it will do the job. but only for one card :
bulk.find({"_id": doc._id, "Cards.1._id": card._id}).update(
{
$set: {"Cards.1.StringContent": card.Content}
});
bulk.find({"_id": doc._id, "Cards.1._id": card._id}).update(
{
$unset: {"Cards.1.Content": 1}
});
What am i missing in my script so this can iterates over several documents and change Content-> StringContent in each Card. ?
EDIT
I have added a bulk.getOperations(); in my script. this is what it returns. Should it not have replaced $ with index ?
/* 1 */
[
{
"originalZeroIndex" : 0.0,
"batchType" : 2.0,
"operations" : [
{
"q" : {
"_id" : "c4af0b19-4c78-4e58-bbe5-ac9e5cce2c3f",
"Cards._id" : "1c8a323f-8d65-4eee-8f06-561760eb5be5"
},
"u" : {
"$set" : {
"Cards.$.StringContent" : "This is a cool test"
}
},
"multi" : false,
"upsert" : false
},
{
"q" : {
"_id" : "c4af0b19-4c78-4e58-bbe5-ac9e5cce2c3f",
"Cards._id" : "1c8a323f-8d65-4eee-8f06-561760eb5be5"
},
"u" : {
"$unset" : {
"Cards.$.Content" : 1.0
}
},
"multi" : false,
"upsert" : false
},
{
"q" : {
"_id" : "c4af0b19-4c78-4e58-bbe5-ac9e5cce2c3f",
"Cards._id" : "1c8a322f-8d65-4eee-8f06-561760eb5be5"
},
"u" : {
"$set" : {
"Cards.$.StringContent" : "This is a test"
}
},
"multi" : false,
"upsert" : false
},
{
"q" : {
"_id" : "c4af0b19-4c78-4e58-bbe5-ac9e5cce2c3f",
"Cards._id" : "1c8a322f-8d65-4eee-8f06-561760eb5be5"
},
"u" : {
"$unset" : {
"Cards.$.Content" : 1.0
}
},
"multi" : false,
"upsert" : false
}
]
}
]

mongodb $in, search deeply nested subdocument

I have the following collections in mongo:
> db.styles.find({ "_id" : "EP01L"}).pretty();
{
"_id" : "EP01L",
"__v" : 5,
"categoryIds" : [
ObjectId("5550dcc7a14c976741483c89"),
ObjectId("5550dcc7a14c976741483c8d")
],
"collectionId" : ObjectId("5550dab4a14c9766418ff2af"),
"colours" : {
"WH" : [
{
"on_sale" : false,
"size_code_id" : "S",
"sku" : "EP01L-WH1"
},
],
"BL" : [
{
"on_sale" : false,
"size_code_id" : "S",
"sku" : "EP01L-BL1"
},
]
},
"fabric" : {
"material" : [
{
"_id" : ObjectId("5550dab4a14c9766418ff2c4"),
"value" : 100
}
],
"type" : ObjectId("5550dab4a14c9766418ff2d1"),
"weight" : {
"ounce" : {
"min" : 4
},
"gram" : {
"min" : 155
}
}
},
"name" : {
"es-ES" : "CAMISETA MANGA LARGA HOMBRE",
"it-IT" : "T-SHIRT UOMO MANICA LUNGA",
"en-UK" : "MEN’S LONG SLEEVE T-SHIRT",
"fr-FR" : "T-SHIRT HOMME MANCHES LONGUES"
},
}
and
> db.attributes.find({"name.en-UK": "Fabric"}).pretty();
{
"_id" : ObjectId("5550dab4a14c9766418ff2dc"),
"values" : {
"source" : [
{
"code" : 1,
"_id" : ObjectId("5550dab4a14c9766418ff2bf"),
"name" : {
"fr-FR" : "Coton",
"it-IT" : "Cotone",
"en-UK" : "Cotton",
"es-ES" : "Algodón"
}
},
{
"code" : 2,
"_id" : ObjectId("5550dab4a14c9766418ff2c0"),
"name" : {
"fr-FR" : "Viscose",
"it-IT" : "Viscosa",
"en-UK" : "Viscose",
"es-ES" : "Viscosa"
}
},
],
"name" : [
{
"_id" : ObjectId("5550dab4a14c9766418ff2cd"),
"name" : {
"en-UK" : "3-ply Loopback"
}
},
{
"_id" : ObjectId("5550dab4a14c9766418ff2db"),
"name" : {
"en-UK" : "Woven Twill"
}
}
]
},
"name" : {
"en-UK" : "Fabric"
}
}
I am trying to write a query to find all the style documents that where fabric.source is either Cotton or Viscose and fabric.name is Woven Twill.
this query gives me all the documents that have fabric.type are Cotton or Viscose
> db.styles.find( { "fabric.type": { $in: [ ObjectId("5550dab4a14c9766418ff2cd"), ObjectId("5550dab4a14c9766418ff2db") ] } } ).count();
3
>
but how do I find all the styles where the size_code_id is S and colours is WH?
Please check the below query :
db.styles.find({
$and:[
{ "colours.WH" :{ $exists:1 } } ,
{ "colours.WH.size_code_id" : "S"}
]
}
).pretty();
If you need to find for "WH" and "BL", you can query like below :
db.styles.find({
$or:[
{
$and:[
{ "colours.WH" :{ $exists:1 } } ,
{ "colours.WH.size_code_id" : "S"}
]
},
{
$and:[
{ "colours.BL" :{ $exists:1 } } ,
{ "colours.BL.size_code_id" : "S"}
]
}
]
}
).pretty();
P.S : If you need to query for the multiple colors say for some 5- 10 different colours, Then you should construct the query dynamically for all those colors using JavaScript language constructs.
Below is the TESTED code for constructing the query dynamically :
// Colours you want to search
var varray = new Array("WH","BL");
var fname = "colours", lname = "size_code_id";
var arr = new Array();
var mquery = {"$or":[]};
for( var i = 0; i < varray.length; i++ )
{
var query = { "$and" : []};
// This line will dynamically construct a key as "colours.WH"
var s1 = fname.concat(".").concat(varray[i]);
// This line will dynamically construct a key as "colours.WH.size_code_id"
var s2 = fname.concat(".").concat(varray[i]).concat(".").concat(lname);
var sub1 = {}, sub2 = {};
sub1[s1] = { $exists:1 };
sub2[s2] = "S";
query["$and"].push(sub1);
query["$and"].push(sub2);
arr.push(query);
}
mquery["$or"] =arr;
db.styles.find(mquery);

MongoDB Length of String or need help in mongoDB mapReduce query

I need some guidence in a query for mongodb. I have a collection of items which contain an array that contains multiple fields, but I only care about one field, which is the barcode field. I need to distiguish the length of the barcode string.
Items.find({this.array['barcode'].length > 6})
It would be great if the above query was possible, but I believe that it's not. I only need a list of barcodes. How do I go about solving this problem? Does mongodb have something to compare length of a string? Or do I have to use a mapReduce query? If I do could I have some guidence on that? I'm not sure how I would go about writing it.
Thank you
Try using a regular expression.
/^\w{6}/ this says match a word that has 6 word characters at the start of the string.
Example:
Setup:
user test;
var createProduct = function(name, barcode){
return {
name : name,
detail: {
barcode : barcode
}
};
};
db.products.drop();
for(var i = 0; i < 10; i++){
db.products.insert( createProduct( "product" + i, "1234567890".substring(0,i+1) ));
}
Document structure:
{
"_id" : ObjectId("540d3ba1242ff352caa6154b"),
"name" : "product0",
"detail" : {
"barcode" : "1"
}
}
Query:
db.products.find({ "detail.barcode" : /^\w{6}/ })
Output:
{ "_id" : ObjectId("540d3ba1242ff352caa61550"), "name" : "product5", "detail" : { "barcode" : "123456" } }
{ "_id" : ObjectId("540d3ba1242ff352caa61551"), "name" : "product6", "detail" : { "barcode" : "1234567" } }
{ "_id" : ObjectId("540d3ba1242ff352caa61552"), "name" : "product7", "detail" : { "barcode" : "12345678" } }
{ "_id" : ObjectId("540d3ba1242ff352caa61553"), "name" : "product8", "detail" : { "barcode" : "123456789" } }
{ "_id" : ObjectId("540d3ba1242ff352caa61554"), "name" : "product9", "detail" : { "barcode" : "1234567890" } }
However, if barcode is a key within an object inside an array AND you only want the matched barcode values. Then you should use an aggregate function to extract the values.
Setup:
user test;
var createProduct = function(name){
var o = {
name : name,
subProducts: []
};
for(var i = 0; i < 10; i++){
o.subProducts.push({
barcode : "1234567890".substring(0,i+1)
});
}
return o;
};
db.products.drop();
db.products.insert( createProduct( "newBrand") );
Document Structure:
{
"_id" : ObjectId("540d4125242ff352caa61555"),
"name" : "newBrand",
"subProducts" : [
{
"barcode" : "1"
},
...
{
"barcode" : "123456789"
},
{
"barcode" : "1234567890"
}
]
}
Aggregate Query:
db.products.aggregate([
{ $unwind : "$subProducts" },
{ $match : { "subProducts.barcode" : /^\w{6}/ } }
]);
Output:
{ "_id" : ObjectId("540d4125242ff352caa61555"), "name" : "newBrand", "subProducts" : { "barcode" : "123456" } }
{ "_id" : ObjectId("540d4125242ff352caa61555"), "name" : "newBrand", "subProducts" : { "barcode" : "1234567" } }
{ "_id" : ObjectId("540d4125242ff352caa61555"), "name" : "newBrand", "subProducts" : { "barcode" : "12345678" } }
{ "_id" : ObjectId("540d4125242ff352caa61555"), "name" : "newBrand", "subProducts" : { "barcode" : "123456789" } }
{ "_id" : ObjectId("540d4125242ff352caa61555"), "name" : "newBrand", "subProducts" : { "barcode" : "1234567890" } }
More info:
http://docs.mongodb.org/manual/reference/operator/query/regex/
Retrieve only the queried element in an object array in MongoDB collection