I Have a collection which has data like {m:1,n:3}
want to update this collection like {m:1,n:3,s:4}
where s= m+n in mongodb,
so for that, I tried
db.data.update({},{$set:{s:(m+n)});
but it doesn't work and I tried multiple things but still haven't a solution. How can I achieve this?
with aggregation you can $addFields and $out to a collection
db.col.aggregate([
{$addFields : {s : {$add:["$m", "$n"]}}},
{$out : "col"}
])
with $project for mongo version less than 3.4
db.col.aggregate([
{$project : {m:1, n:1, s : {$add:["$m", "$n"]}}},
{$out : "col"}
])
result
> db.col.drop()
true
> db.col.insert({m:2,n:4})
WriteResult({ "nInserted" : 1 })
> db.col.find()
{ "_id" : ObjectId("5a911efc6bb20635697c6b17"), "m" : 2, "n" : 4 }
> db.col.aggregate([{$addFields : {s : {$add:["$m", "$n"]}}},{$out : "col"}])
> db.col.find()
{ "_id" : ObjectId("5a911efc6bb20635697c6b17"), "m" : 2, "n" : 4, "s" : 6 }
>
Related
This question already has answers here:
How do I update Array Elements matching criteria in a MongoDB document?
(2 answers)
Closed 4 years ago.
I have an object that looks like the following:
> db.delegate_list.find({"name": "delegateList"}).pretty()
{
"_id" : ObjectId("5becd1e0adeb2717c087cec5"),
"name" : "delegateList",
"delegates" : [
{
"address" : "tz1SUgyRB8T5jXgXAwS33pgRHAKrafsdkjhc",
"sync" : false
},
{
"address" : "tz1MecudVJnFZN5FSrriu8ULz2d6dDTR7KaM",
"sync" : false
}
]
}
I am trying to update the sync field for specific object in the array. So for example if I update the sync field for the object at index 0 or address tz1SUgyRB8T5jXgXAwS33pgRHAKrafsdkjhc by doing the following it yields:
> db.delegate_list.update({"name":"delegateList"}, {$set:{"delegates.0.sync": true}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.delegate_list.find({"name": "delegateList"}).pretty()
{
"_id" : ObjectId("5becd1e0adeb2717c087cec5"),
"name" : "delegateList",
"delegates" : [
{
"address" : "tz1SUgyRB8T5jXgXAwS33pgRHAKrafyg87Yc",
"sync" : true
},
{
"address" : "tz1MecudVJnFZN5FSrriu8ULz2d6dDTR7KaM",
"sync" : false
}
]
}
It works as expected, but if I perform the same update command to switch back sync:false, it gives me a malformed object, while deleting the rest of the array:
> db.delegate_list.update({"name":"delegateList"}, {$set:{"delegates.0.sync": false}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.delegate_list.find({"name": "delegateList"}).pretty()
{
"_id" : ObjectId("5becd1e0adeb2717c087cec5"),
"name" : "delegateList",
"delegates" : {
"address" : "tz1SUgyRB8T5jXgXAwS33pgRHAKrafyg87Yc",
"sync" : true,
"0" : {
"sync" : false
}
}
}
You can update specific array item, if item match your case using $ operator
db.delegate_list.update({"delegates.address":"tz1SUgyRB8T5jXgXAwS33pgRHAKrafyg87Yc"}, {$set:{"delegates.$.sync": false}})
It will update the sync filed which address is "tz1SUgyRB8T5jXgXAwS33pgRHAKrafyg87Yc"
only, and not going to add any extra field.
I am caching data from an online resource for future use in machine learning. This data is canonical and has no missing entries.
In the event that the real-time connection is dropped or the machine rebooted, I have a safeguard in place that does a historical search for a range of ids that are missing from the cache.
What I have yet to implement, however, is a mechanism for searching through the collection and identifying ranges where id values have been skipped.
For instance:
{"entry_id": 27497713, ...}
{"entry_id": 27497761, ...}
This data has a clear gap where entries are missing between 27497713 and 27497761.
Is there a way I can find such a gap using queries? Perhaps at least narrowing it down by selecting values between two ranges and checking the count of returned entries? Given how many entries the collection contains, I am trying to avoid lots of queries for efficiency.
can you try this aggregation
$group - get $min and $max
$addFields - generate $range by $min and $max entry_id
$lookup - self lookup with generated range ids and entry ids
$project - get only non matching range ids using setDifference
pipeline
db.entries.aggregate(
[
{$group : {_id : null, min : {$min : "$entry_id"}, max : {$max : "$entry_id"}}},
{$addFields : {rangeIds : {$range : ["$min", "$max"]}}},
{$lookup : {from : "entries", localField : "rangeIds", foreignField : "entry_id", as : "entries"}},
{$project : {_id :0, missingIds : {$setDifference : ["$rangeIds", "$entries.entry_id"]}}}
]
)
collection
> db.entries.find()
{ "_id" : ObjectId("5a6fea9b7346ce591a17ad22"), "entry_id" : 27497713 }
{ "_id" : ObjectId("5a6fea9b7346ce591a17ad23"), "entry_id" : 27497761 }
{ "_id" : ObjectId("5a6fea9b7346ce591a17ad24"), "entry_id" : 27497750 }
>
aggregate result
> db.entries.aggregate( [ {$group : {_id : null, min : {$min : "$entry_id"}, max : {$max : "$entry_id"}}}, {$addFields : {rangeIds : {$range : ["$min", "$max"]}}}, {$lookup : {from : "entries", localField : "rangeIds", foreignField : "entry_id", as : "entries"}}, {$project : {_id :0, missingIds : {$setDifference : ["$rangeIds", "$entries.entry_id"]}}} ] )
{ "missingIds" : [ 27497714, 27497715, 27497716, 27497717, 27497718, 27497719, 27497720, 27497721, 27497722, 27497723, 27497724, 27497725, 27497726, 27497727, 27497728, 27497729, 27497730, 27497731, 27497732, 27497733, 27497734, 27497735, 27497736, 27497737, 27497738, 27497739, 27497740, 27497741, 27497742, 27497743, 27497744, 27497745, 27497746, 27497747, 27497748, 27497749, 27497751, 27497752, 27497753, 27497754, 27497755, 27497756, 27497757, 27497758, 27497759, 27497760 ] }
>
I want to create an index so that my DB does not allow me to insert documents whose value for the key lema is already present in some document of the DB. I did this:
db.version()
3.0.14
> db.rae.ensureIndex({"lema":1, unique: true})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 2,
"note" : "all indexes already exist",
"ok" : 1
}
> db.rae.insert({"lema":"a"})
WriteResult({ "nInserted" : 1 })
> db.rae.insert({"lema":"a"})
WriteResult({ "nInserted" : 1 })
> db.rae.insert({"lema":"a"})
WriteResult({ "nInserted" : 1 })
> db.rae.find()
{ "_id" : ObjectId("591a0ce372329f3162a314cc"), "lema" : "a" }
{ "_id" : ObjectId("591a0ce472329f3162a314cd"), "lema" : "a" }
{ "_id" : ObjectId("591a0ce572329f3162a314ce"), "lema" : "a" }
Clearly the DB is letting me insert documents whose values of lema are all a. How can I fix this? Thanks a lot
From Stennie's comment:
I should use createIndex instead of ensureIndex. Also I had a mistake, I should use db.rae.createIndex({"lema":1}, { unique: true}).
I'm using for the first time a Mongodb and I got a very weird bug.. I have a 'games' collection and I can't make a search with _id query on it..
I try directly on the mongo shell and this is the result :
> db.games.count()
0
> db.games.insert({created:'ok'})
WriteResult({ "nInserted" : 1 })
> db.games.find()
{ "_id" : ObjectId("54f7364d1f2f9378d7a5ddde"), "created" : "ok" }
> db.games.findOne({_id:'54f7364d1f2f9378d7a5ddde'})
null
> db.games.find({_id:'54f7364d1f2f9378d7a5ddde'})
>
I really don't know what is going on ? I was thinking about a weird index on _id but I found nothing..
> db.games.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "cobra.games"
}
]
>
This can maybe help you
> db.version()
2.6.5
Someone have an idea ?
try:
db.games.find({"_id" : ObjectId("54f7364d1f2f9378d7a5ddde")})
The type of the data stored in the key _id is of ObjectId and your were searching for a String. So you the types were not matching. MongoDB has not auto-casting of String to ObjectId. This Error can also happen if your store your numbers as a Long but in your query you enter an Integer.
Given the following data set:
{ "_id" : ObjectId("510458b188ce1d16e616129b"), "codes" : [ "oxtbyr", "xstute" ], "name" : "Ciao Mambo", "permalink" : "ciaomambo", "visits" : 1 }
{ "_id" : ObjectId("510458b188ce1d16e6161296"), "codes" : [ "zpngwh", "odszfy", "vbvlgr" ], "name" : "Anthony's at Spokane Falls", "permalink" : "anthonysatspokanefalls", "visits" : 0 }
How can I convert this python/pymongo sort into something that will work with the MongoDB aggregation framework? I'm sorting results based on the number of codes within the codes array.
z = [(x['name'], len(x['codes'])) for x in restaurants]
sorted_by_second = sorted(z, key=lambda tup: tup[1], reverse=True)
for x in sorted_by_second:
print x[0], x[1]
This works in python, I just want to know how to accomplish the same goal on the MongoDB query end of things.
> db.z.aggregate({ $unwind:'$codes'},
{ $group : {_id:'$_id', count:{$sum:1}}},
{ $sort :{ count: 1}})