MongoDB pullAll objects with multiple arguments - mongodb

I just want to remove several Objects in from my array in mongoDB using pullAll
db.collection.update({'_id': ObjectId(".....")}, { $pullAll : { 'notifications' : [{'type' : type}, {'id': id}]} })
Why is this not working? What is the correct syntax?
Update:
the document is:
{
"_id" : ObjectId("......"),
"notifications" : [ { "type" : "aaa",
"id" : "123" },
{ "type" : "bbb",
"id" : "123" },
{ "type" : "ccc",
"id" : "234" }]
}

Your problem may be one of two places:
First your update has a syntax issue:
db.collection.update({'_id': ObjectId(".....")},
{ $pullAll :
{ 'notifications' : [{'type' : type}, {'id': id}]
}
}
)
should be:
db.collection.update({'_id': ObjectId(".....")},
{ $pullAll :
{ 'notifications' : [{'type' : type, 'id': id}]
}
}
)
Note I removed }, { and joined type and id into a single JSON subdocument.
The other issue is your array elements seem to have id values which are strings of form "123" - are you sure you are passing a string to your update statement? String "123" is not equal to integer 123.

To use $pullAll you need to match the whole object exactly. Why not just use $pull, I'm sure it would suit your needs

Related

Retrieving value of an emedded object in mongo

Followup Question
Thanks #4J41 for your spot on resolution. Along the same lines, I'd also like to validate one other thing.
I have a mongo document that contains an array of Strings, and I need to convert this particular array of strings into an array of object containing a key-value pair. Below is my curent appraoch to it.
Mongo Record:
Same mongo record in my initial question below.
Current Query:
templateAttributes.find({platform:"V1"}).map(function(c){
//instantiate a new array
var optionsArray = [];
for (var i=0;i< c['available']['Community']['attributes']['type']['values'].length; i++){
optionsArray[i] = {}; // creates a new object
optionsArray[i].label = c['available']['Community']['attributes']['type']['values'][i];
optionsArray[i].value = c['available']['Community']['attributes']['type']['values'][i];
}
return optionsArray;
})[0];
Result:
[{label:"well-known", value:"well-known"},
{label:"simple", value:"simple"},
{label:"complex", value:"complex"}]
Is my approach efficient enough, or is there a way to optimize the above query to get the same desired result?
Initial Question
I have a mongo document like below:
{
"_id" : ObjectId("57e3720836e36f63695a2ef2"),
"platform" : "A1",
"available" : {
"Community" : {
"attributes" : {
"type" : {
"values" : [
"well-known",
"simple",
"complex"
],
"defaultValue" : "well-known"
},
[......]
}
I'm trying to query the DB and retrieve only the value of defaultValue field.
I tried:
db.templateAttributes.find(
{ platform: "A1" },
{ "available.Community.attributes.type.defaultValue": 1 }
)
as well as
db.templateAttributes.findOne(
{ platform: "A1" },
{ "available.Community.attributes.type.defaultValue": 1 }
)
But they both seem to retrieve the entire object hirarchy like below:
{
"_id" : ObjectId("57e3720836e36f63695a2ef2"),
"available" : {
"Community" : {
"attributes" : {
"type" : {
"defaultValue" : "well-known"
}
}
}
}
}
The only way I could get it to work was with find and map function, but it seems to be convoluted a bit.
Does anyone have a simpler way to get this result?
db.templateAttributes.find(
{ platform: "A1" },
{ "available.Community.attributes.type.defaultValue": 1 }
).map(function(c){
return c['available']['Community']['attributes']['type']['defaultValue']
})[0]
Output
well-known
You could try the following.
Using find:
db.templateAttributes.find({ platform: "A1" }, { "available.Community.attributes.type.defaultValue": 1 }).toArray()[0]['available']['Community']['attributes']['type']['defaultValue']
Using findOne:
db.templateAttributes.findOne({ platform: "A1" }, { "available.Community.attributes.type.defaultValue": 1 })['available']['Community']['attributes']['type']['defaultValue']
Using aggregation:
db.templateAttributes.aggregate([
{"$match":{platform:"A1"}},
{"$project": {_id:0, default:"$available.Community.attributes.type.defaultValue"}}
]).toArray()[0].default
Output:
well-known
Edit: Answering the updated question: Please use aggregation here.
db.templateAttributes.aggregate([
{"$match":{platform:"A1"}}, {"$unwind": "$available.Community.attributes.type.values"},
{$group: {"_id": null, "val":{"$push":{label:"$available.Community.attributes.type.values",
value:"$available.Community.attributes.type.values"}}}}
]).toArray()[0].val
Output:
[
{
"label" : "well-known",
"value" : "well-known"
},
{
"label" : "simple",
"value" : "simple"
},
{
"label" : "complex",
"value" : "complex"
}
]

removing an object from a mongodb document

I have a document in Mongodb collection, where I want to remove an object, using title key.
I tried using $unset, but it only removes the title key not the object to which it belongs.
{
"_id" : ObjectId("576b63d49d20504c1360f688"),
"books" : [
{
"art_id" : ObjectId("574e68e5ac9fbac82489b689"),
"title" :"abc",
"price" : 40
},
{
"art_id" : ObjectId("575f9badada0500d192c53f4"),
"title" : "xyz",
"price" : 20
},
{
"art_id" : ObjectId("57458224d86b3d1561150f17"),
"title" : "def",,
"price" : 30
}
],
"user_id" : "575570c315e27d13167dfc0d"
}
To remove the entire object that contains the query object use db.remove() query.
For your case:
db.yourcollection.remove({"books.title": "abc"});
Please double check the format in which the element of array is referenced.
This removes the entire objects that contains the embedded query obj. To remove only a single object, provide it with another field to uniquely identify it.
If you only want to remove the object that contains the title field from the array but wants to keep the object that contains the array, then please use the $pull operator. This answer will be of help.
Example: if you want to remove object
{
"art_id" : ObjectId("574e68e5ac9fbac82489b689"),
"title" :"abc",
"price" : 40
}
just from the array but keep the parent object like
{
"_id" : ObjectId("576b63d49d20504c1360f688"),
"books" : [
{
"art_id" : ObjectId("575f9badada0500d192c53f4"),
"title" : "xyz",
"price" : 20
},
{
"art_id" : ObjectId("57458224d86b3d1561150f17"),
"title" : "def",,
"price" : 30
}
],
"user_id" : "575570c315e27d13167dfc0d"
}
use
db.mycollection.update(
{'_id': ObjectId("576b63d49d20504c1360f688")},
{ $pull: { "books" : { "title": "abc" } } },
false,
true
);
$unset won't remove the object from an array. The $unset operator deletes a particular field. doc.
Use $pull instead.
The $pull operator removes from an existing array all instances of a value or values that match a specified condition.
Try following query
db.collName.update({$pull : {books:{title:abc}}})
Refer $pull-doc
Hope this will help you.
And if... ¿Do I want to delete an object that is inside a document and not as an array?
{
"_id" : ObjectId("576b63d49d20504c1360f688"),
"books" : {
"574e68e5ac9fbac82489b689": {
"art_id" : ObjectId("574e68e5ac9fbac82489b689"),
"title" :"abc",
"price" : 40
},
"575f9badada0500d192c53f4": {
"art_id" : ObjectId("575f9badada0500d192c53f4"),
"title" :"xyz",
"price" : 20
},
"57458224d86b3d1561150f17": {
"art_id" : ObjectId("57458224d86b3d1561150f17"),
"title" : "def",
"price" : 30
}
},
"user_id" : "575570c315e27d13167dfc0d"
}
The solutions is this:
db.auctions.update(
{'_id': ObjectId("576b63d49d20504c1360f688")},
{$unset: {"books.574e68e5ac9fbac82489b689":
{_id: "574e68e5ac9fbac82489b689"}}})
Try using pull.
https://docs.mongodb.com/manual/reference/operator/update/pull/
$pull
The $pull operator removes from an existing array all instances of a value or values that match a specified condition.
The $pull operator has the form:
{ $pull: { <field1>: <value|condition>, <field2>: <value|condition>, ... } }
To specify a <field> in an embedded document or in an array, use dot notation.
Try in the mongo shell
db.yourcollection.remove({books:[{title:'title_you_want'}]})
Careful with the braces.

MongoDB fields limitation in array [duplicate]

This question already has answers here:
Retrieve only the queried element in an object array in MongoDB collection
(18 answers)
Closed 8 years ago.
I am looking for a way - and dont even now if this is possible - just to return a part of a list saved in mongodb.
Lets have a look in my currently document:
{
_id : 'MyId',
name : 'a string',
conversations : [
{
user : 'Mike',
input : 'Some input'
},
{
user : 'Stephano',
input : 'some other input'
}
]
}
What I now want to do is smth like this:
var myOutput;
myOutput = db.my_collection.find(
{
_id : 'MyId',
'conversations.user' : 'Mike'
}, {
_id : 1,
name : 1,
conversations : {
$where : {
user : 'Mike'
}
}
});
Goal is it just to get back the conversation array item where user has the value Mike.
Is this still possible in MongoDB ? didn't found any reference in the documentation for the field limitations in mongoDB.
Use the $ positional operator in a projection:
> db.my_collection.find({ "_id" : "MyId", "conversations.user" : "Mike" },
{ "_id" : 1, "name" : 1, "conversations.$" : 1 })
{
"_id" : 'MyId',
"name" : 'a string',
"conversations" : [
{ "user" : 'Mike', "input" : 'Some input' }
]
}
This projects only first matching array element.
Are you aware of the aggregation pipeline?
db.my_collection.aggregate([
{ "$match": { "_id": "MyId"}}, { "$unwind": "$conversations"},
{ "$match": {"conversations.user": "Mike"}}
])
Output
{
"_id" : "MyId",
"name" : "a string",
"conversations" :
{
"user" : "Mike",
"input" : "Some input"
}
}

$type for Array field returns false

I have a collection having following data:
{"_id" : ObjectId("5220222f8188d30ce85d61cc"),
"testfields" : [{
"test_id" : 1,
"test_name" : "xxxx"
}]
}
when I query :
db.testarray.find({ "testfields" : { "$type" : 4 } })
it returns no data,but same returns data when I do:
db.testarray.find({ "$where" : "Array.isArray(this.testfields)" })
It returns data, do the type:4 identifies some other kind of list?
Because testfields is an Array, $type : 4 will perform the "is array" check against every element in testfields as opposed to testfields itself. Since your testfields contains just one Object, it does not get returned.
If on the other hand you inserted the following into your collection,
db.testarray.insert( { "testfields" : [ { "test_id" : 1, "test_name" : "xxxx" },
[ "a", "b" ] ] } );
it would get returned because now one of the elements of testfields is an Array.
More info explaining this in the docs.

How to update particular array element in MongoDB

I am newbie in MongoDB. I have stored data inside mongoDB in below format
"_id" : ObjectId("51d5725c7be2c20819ac8a22"),
"chrom" : "chr22",
"pos" : 17060409,
"information" : [
{
"name" : "Category",
"value" : "3"
},
{
"name" : "INDEL",
"value" : "INDEL"
},
{
"name" : "DP",
"value" : "31"
},
{
"name" : "FORMAT",
"value" : "GT:PL:GQ"
},
{
"name" : "PV4",
"value" : "1,0.21,0.00096,1"
}
],
"sampleID" : "Job1373964150558382243283"
I want to update the value to 11 which has the name as Category.
I have tried below query:
db.VariantEntries.update({$and:[ { "pos" : 117199533} , { "sampleID" : "Job1373964150558382243283"},{"information.name":"Category"}]},{$set:{'information.value':'11'}})
but Mongo replies
can't append to array using string field name [value]
How one can form a query which will update the particular value?
You can use the $ positional operator to identify the first array element to match the query in the update like this:
db.VariantEntries.update({
"pos": 17060409,
"sampleID": "Job1373964150558382243283",
"information.name":"Category"
},{
$set:{'information.$.value':'11'}
})
In MongoDB you can't adress array values this way. So you should change your schema design to:
"information" : {
'category' : 3,
'INDEL' : INDEL
...
}
Then you can adress the single fields in your query:
db.VariantEntries.update(
{
{"pos" : 117199533} ,
{"sampleID" : "Job1373964150558382243283"},
{"information.category":3}
},
{
$set:{'information.category':'11'}
}
)