The first answer google returned is: How do I remove a field completely from Mongo?
And the documentation: https://docs.mongodb.com/manual/reference/operator/update/unset/
I tried:
db.amazon_rev.update({}, {$unset: {'meta.asin': true}}, false, true)
db.amazon_rev.update({}, {$unset: {'meta.asin':1}}, false, true)
db.amazon_rev.update({}, {$unset: {'meta.asin': ''}}, false, true)
db.amazon_rev.update({}, {$unset: {'meta.asin': ''}}, {multi: true})
db.amazon_rev.update({}, {$unset: {'meta.asin':1}}, {multi: true})
db.amazon_rev.update({}, {$unset: {'meta.asin': true}}, {multi: true})
Every time it says:
WriteResult({ "nMatched" : 237199, "nUpserted" : 0, "nModified" : 0 })
and nothing changed:
(This collection was merged together from two collections (review and meta, both indexed by asin) by mongodb aggregation $lookup)
db.amazon_rev.findOne()
{
"_id" : ObjectId("57f21916672286a104572738"),
"reviewerID" : "A2E2I6B878????",
"asin" : "B000GI????",
"reviewerName" : "Big????",
"helpful" : [
0,
0
],
"unixReviewTime" : 137???????,
"reviewText" : "........................................",
"overall" : 5,
"reviewTime" : "????, 2013",
"summary" : "............",
"meta" : [
{
"_id" : ObjectId("57f218e2672286a10456af7d"),
"asin" : "B000GI????",
"categories" : [
[
".................."
]
]
}
]
}
Is there something I missed? Thanks for any suggestion!
Can try using positional operator $ and check that field exist or not using $exists. this process only unset the first element of an array.
db.amazon_rev.update({
"meta.asin": {$exists: true}
},{
$unset: {
"meta.$.asin" : true
}
},false,true);
if you want to delete each asin from meta array then better process is find documents and remove each meta.asin then save again that document.
Related
I want to update a specific element by its id in a subarray of a document.
I use arrayFilters. If I directly specify the id in the arrayFilter with {"members1.id":"311129357362135041"} it modifies it as expected:
> db.guilds.updateOne({id:"561235799233003551"}, {$set: {"members.$[members1]": {test:"hi"}}}, {upsert: true, arrayFilters: [{"members1.id":"311129357362135041"}]})
> { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
but if I try to match the element with {"members1":{$elemMatch: {id:"311129357362135041"}}} it doesn't update/find the element:
> db.guilds.updateOne({id:"561235799233003551"}, {$set: {"members.$[members1]": {id:"311129357362135041"}}}, {upsert: true, arrayFilters: [{"members1":{$elemMatch: {id:"311129357362135041"}}}]})
> { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }
Why is that or is there a better solution?
I have a document with a schema in mongodb that looks like this:
{
"_id" : ObjectId("572f88424de8c74a69d4558c"),
"storecode" : "ABC",
"credit" : true,
"group" : [
{
"group_name" : "Frequent_Buyer",
"time" : NumberLong("1462732865712"),
}
],
}
I want to add on the _id part for the first object in the array under group so it looks like this:
{
"_id" : ObjectId("572f88424de8c74a69d4558c"),
"storecode" : "ABC",
"credit" : true,
"group" : [
{
"group_name" : "Frequent_Buyer",
"time" : NumberLong("1462732865712"),
"_id" : "573216fee4430577cf35e885"
}
],
}
When I try this code it fails:
db.customer.update({ "_id": ObjectId("572f88424de8c74a69d4558c") },{ "$set": { "group.$._id": "573216fee4430577cf35e885"} })
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16837,
"errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: groups.$._id"
}
})
However, if I adjust the code slightly and add on an extra criteria for querying, it works:
db.customer.update({ "_id": ObjectId("572f88424de8c74a69d4558c"), "group.groupname": "Frequent_Buyer" },{ "$set": { "group.$._id": "573216fee4430577cf35e885"} })
Results:
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Why did the first command not work but the second command work?
This is the expected result. To use the positional $ update operator, the array field must appear as part of the query document as mentioned in the documentation.
When used with update operations, e.g. db.collection.update() and db.collection.findAndModify(),
the positional $ operator acts as a placeholder for the first element that matches the query document, and
the array field must appear as part of the query document.
For example If you don't want to filter your documents using group_name, simply add group: { "$exists": true } or "group.0": { "$exists": true } to your query criteria. You query will then look like this:
db.customer.updateOne(
{
"_id": ObjectId("572f88424de8c74a69d4558c"),
"group.0": { "$exists": true}
},
{ "$set": { "group.$._id": "573216fee4430577cf35e885" } }
)
Last and not least, you should be using updateOne or updateMany because update is deprecated in official language driver.
I am performing an aggregate query where I want to select a single document that contains an array of documents which I then filter out based a condition. I want to implement a paging system so I am relying on the $skip operator.
The issue is that even after ordering my documents $skip will start from the first documents and instead I want the documents to be skipped starting from the end.
myCollection.aggregate( {$match : {title : title, available : true} },
{$unwind : '$versions'},
{$match : {'versions.active' : true } }
, {$sort : {'versions.dateAdded' : 1}},
{$skip : offset},
{$limit : 10} );
where offset is a value I would calculate.
Say I have the query selects the document
{
title : 'ab',
available : true,
versions : [{name : 'v1', active : true, dateAdded: ISODATE...},
{name : 'v2', active : true, dateAdded: ISODATE...},
{name : 'v3', active : true, dateAdded: ISODATE...},
{name : 'v4', active : true, dateAdded: ISODATE...},
{name : 'v5', active : true, dateAdded: ISODATE...}]
}
I want the $skip operator to start from the last array element. I thought a possible solution might be to return the number of elements that were selected from the {$match : {'versions.active' : true}} and then subtracting the offset, I tried the $size operator but that just returns the full size of the array and that only those elements that satisfy the condition.
I'm presuming because your sort does not contain any other keys that "title" is unique here, and this seems to be the case if "skip/limit" works for you basically here. Therefore, just "reverse" the sort order:
myCollection.aggregate([
{$match : {title : title, available : true} },
{$unwind : '$versions'},
{$match : {'versions.active' : true } }
{$sort : {'versions.dateAdded' : -1}},
{$skip : offset},
{$limit : 10},
{$sort : {'versions.dateAdded' : 1}}
])
And that means going "backwards" through the list, and then the last $sort re-orders the list after the "skip/limit".
In the shell, my query is:
db.checkin_4e95ae0926abe9ad28000001.update({location_city:"New York"}, {location_country: "FUDGE!"});
However, it doesn't actually update my records. It doesn't error either. When I do a db.checkin_4e95ae0926abe9ad28000001.find({location_city:"New York"}); after running this, I get all my results but the location_country has not changed:
{
"_id": ObjectId("4e970209a0290b70660009e9"),
"addedOn": ISODate("2011-10-13T15:21:45.772Z"),
"location_address1": "",
"location_city": "New York",
"location_country": "United States",
"location_latLong": {
"xLon": -74.007124,
"yLat": 40.71455
},
"location_source": "socialprofile",
"location_state": "New York",
"location_zip": ""
}
This is because in second parameter of update function you need to use $set operator to update location_country as in example below:
db.checkin_4e95ae0926abe9ad28000001.update(
{location_city:"New York"}, //find criteria
// this row contains fix with $set oper
{ $set : { location_country: "FUDGE!"}});
Here you can find a list of available update operators.
Changed in version 3.6.
Following is the syntax for update :
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ]
}
)
Example :
db.getCollection('products').update({},{$unset: {translate:1, qordoba_translation_version:1}}, {multi: true})
In your example :
db.checkin_4e95ae0926abe9ad28000001.update(
{location_city:"New York"}, //query
// $update query
{ $set : { location_country: "FUDGE!"}});
By default, the update() method updates a single document. Set the Multi Parameter to update all documents that match the query criteria.
Example 2 :
db.checkin_4e95ae0926abe9ad28000001.update(
{location_city:"New York"}, //query
// $update query
{ $set : { location_country: "FUDGE!"}}, {multi: true});
db.m_country.update(
{"countryId": "962a0935-bf3d-4f63-a53c-254760273ede"},
{$set: {'countryPopulation': '12540000'}})
Before Update
> db.student.find({name:"Venky"}).pretty();
{
"_id" : ObjectId("6012e64dc2979ddffe1e5df9"),
"name" : "Venky",
"dept" : "MCA",
"age" : "26",
"phone" : "89786465"
}
Update Command
> db.student.update({name:"Venky"},{$set: {name:"DODDANNA CHAWAN",dept:"MCA(CS)", age:"25", phone:"1234567890"}});
Find Command See Result
> db.student.find({name:"DODDANNA CHAWAN"}).pretty();
After Updated Result
{
"_id" : ObjectId("6012e64dc2979ddffe1e5df9"),
"name" : "DODDANNA CHAWAN",
"dept" : "MCA(CS)",
"age" : "25",
"phone" : "1234567890"
}
in real life use unique "_id" to match the document becuase names will found as duplicates
I am new in mongodb and i want to remove the some element in array.
my document as below
{
"_id" : ObjectId("4d525ab2924f0000000022ad"),
"name" : "hello",
"time" : [
{
"stamp" : "2010-07-01T12:01:03.75+02:00",
"reason" : "new"
},
{
"stamp" : "2010-07-02T16:03:48.187+03:00",
"reason" : "update"
},
{
"stamp" : "2010-07-02T16:03:48.187+04:00",
"reason" : "update"
},
{
"stamp" : "2010-07-02T16:03:48.187+05:00",
"reason" : "update"
},
{
"stamp" : "2010-07-02T16:03:48.187+06:00",
"reason" : "update"
}
]
}
in document, i want to remove first element(reason:new) and last element(06:00) .
and i want to do it using mongoquery, i am not using any java/php driver.
If I'm understanding you correctly, you want to remove the first and last elements of the array if the size of the array is greater than 3. You can do this by using the findAndModify query. In mongo shell you would be using this command:
db.collection.findAndModify({
query: { $where: "this.time.length > 3" },
update: { $pop: {time: 1}, $pop: {time: -1} },
new: true
});
This would find the document in your collection which matches the $where clause.
The $where field allows you to specify any valid javascript method. Please note that it applies the update only to the first matched document.
You might want to look at the following docs also:
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-JavascriptExpressionsand%7B%7B%24where%7D%7D for more on the $where clause.
http://www.mongodb.org/display/DOCS/Updating#Updating-%24pop for
more on $pop.
http://www.mongodb.org/display/DOCS/findAndModify+Command for more
on findAndModify.
You could update it with { $pop: { time: 1 } } to remove the last one, and { $pop: { time : -1 } } to remove the first one. There is probably a better way to handle it though.
#javaamtho you cannot test for a size greater than 3 but only if it is exactly 3, for size greater than x number you should use the $inc operator and have a field you either 1 or -1 to in order to keep track when you remove or add items (use a separate field outside the array as below, time_count)
{
"_id" : ObjectId("4d525ab2924f0000000022ad"),
"name" : "hello",
"time_count" : 5,
"time" : [
{
"stamp" : "2010-07-01T12:01:03.75+02:00",
"reason" : "new"
},
{
"stamp" : "2010-07-02T16:03:48.187+03:00",
"reason" : "update"
},
{
"stamp" : "2010-07-02T16:03:48.187+04:00",
"reason" : "update"
},
{
"stamp" : "2010-07-02T16:03:48.187+05:00",
"reason" : "update"
},
{
"stamp" : "2010-07-02T16:03:48.187+06:00",
"reason" : "update"
}
]
}
If you would like to leave these time elements, you can use aggregate command from mongo 2.2+ to retrieve min and max time elements, unset all time elements, and push min and max versions (with some modifications it could do your job):
smax=db.collection.aggregate([{$unwind: "$time"},
{$project: {tstamp:"$time.stamp",treason:"$time.reason"}},
{$group: {_id:"$_id",max:{$max: "$tstamp"}}},
{$sort: {max:1}}])
smin=db.collection.aggregate([{$unwind: "$time"},
{$project: {tstamp:"$time.stamp",treason:"$time.reason"}},
{$group: {_id:"$_id",min:{$min: "$tstamp"}}},
{$sort: {min:1}}])
db.students.update({},{$unset: {"scores": 1}},false,true)
smax.result.forEach(function(o)
{db.collection.update({_id:o._id},{$push:
{"time": {stamp: o.max ,reason: "new"}}},false,true)})
smin.result.forEach(function(o)
{db.collection.update({_id:o._id},{$push:
{"time": {stamp: o.min ,reason: "update"}}},false,true)})
db.collection.findAndModify({
query: {$where: "this.time.length > 3"},
update: {$pop: {time: 1}, $pop{time: -1}},
new: true });
convert to PHP