MongoEngine delete dict key from object field - mongodb

I have a pretty complex Flask website with lots of DB interaction but have got stuck with a seemingly simple delete function!
I am trying to delete key 56 from sensordict in the (simplified) SiteConfig document below using MongoEngine
{
"_id" : "12345",
"sensordict" : {
"56" : {
"currentval" : 1.2,
"devicetype" : NumberInt(2)
},
"70" : {
"currentval" : 31.0,
"devicetype" : NumberInt(2)
}
},
"siteserial" : "45678",
"status" : NumberInt(1)
}
Code tried below where sensorid = '56':
def delete_sensor(siteconfig, sensorid):
dbsite = SiteConfig.objects(id=siteconfig.id).first()
dbsite.update(unset__sensordict__S=sensorid)
dbsite.save()
The code is failing at the update with mongoengine.errors.OperationError: Update failed (The positional operator did not find the match needed from the query. Unexpanded update: sensordict.$)
I suspect this is a simple one but have been way down the rabbit hole for a couple of hours on this one and any help would be much appreciated
Thanks
Bill

dbsite.update(unset__sensordict__S=sensorid) should be dbsite.update(unset__sensordict__56=1) since you have to unset the field with key '56'. This should work

Related

Query on all descendants of node

Given a collection of MongoDb documents with a property "myContacts" like this:
{
"_id": 123,
"myContacts" : {
"contacts" : {
"10" : {
"_id" : NumberLong(10),
"name" : "c1",
"prop" : true
},
"20" : {
"_id" : NumberLong(20),
"name" : "c2"
},
}
}
}
I want to select all documents, where at least one contact lacks the "prop" field.
I figured out a general query:
db.getCollection('xyz').find({ 'myContacts.contacts.???.prop': { $exists: false } })
The problem is that IDs of the contacts are part of the path and I cannot know them ahead. I want sth like 'myContacts.contacts.$anyChild.prop', but cannot find sth similar in the mongo docs.
Does it mean there is no way to do it?
PS: I cannot change the document structure, a live app uses it. I've spent some time with Google and my bet it's not possible. I however would like an opinion from people who have experience with Mongo.
Thank you guys for helpful comments, this got me going! I could get the results I wanted with:
db.getCollection('xyz').aggregate([{$project: {_id:1, contacts:{$objectToArray: "$myContacts.contacts"}}}, {$match: {"contacts.v.prop" : null}}])

pymongo bson.code pass in variable

I'm using pymongo's map_reduce framework for extracting some data out from mongodb. This is how my data look like:
{
"_id" : ObjectId("566f570e3816dc2fe631db4f"),
"property_id" : 5594.0000000000000000,
"reservation_id" : "2544430.1",
"updated" : ISODate("2015-12-15T02:04:33.000Z"),
"offer_list" : {
"68799" : {
"pitched" : "no",
"accepted" : "no"
},
"68801" : {
"pitched" : "no",
"accepted" : "no"
}
},
"status" : "awarded",
"comments" : "",
"agent_id" : 1.0000000000000000,
"created" : ISODate("2015-12-14T23:55:52.000Z")
}
I will need to get all record counts for each agent after some date using pymongo.
The mapper function would look like:
mapper = Code("""function(){
if(this.created>start_date){
emit(this.agent_id, 1);
})
in which start_date would be a variable passed in from python code.
By reading the document I think the scope should be set but I could not find any documentation on how to do that. I knew nothing about javascript. Can anyone help?
Thanks in advance!
The problem was fixed using the query keyword.
collection.map_reduce(mapper, reducer, "myresults", query={"created":{"$gte":start_date, "$lt":end_date}})

Updating MongoDB object field

I have searched and tried many answers but I can't seem to get this working. I have a user in MongoDB (db.users...) and I'm trying to update a field titled 'role' in one particular document. If I perform a :
db.users.find();
I get:
{ "_id" : "fDx2g34G8vxsDu3vf", "createdAt" : ISODate("2014-06-03T16:31:47.382Z"),
"emails" : [ { "address" : "andrewmlarking#gmail.com", "verified" : false } ],
"profile" : { "name" : "Admin", "role" : "user", "division" : "0", "enrolled" : "false" },
"services" : { "password" : { "srp" : { "identity" "dEad06c_5mjzsprUzgRyh6tB66OiaybdLzbnxFzO1xh",
"salt" : "zqWsh etc etc
Which is fine, if I then perform a:
db.users.update({_id:"2xnoy3jqcHCaFp7Br"}, { role:"admin"});
I get a:
assert failed : need an object Error: Printing Stack Trace
at printStackTrace (src/mongo/shell/utils.js:37:15)
at doassert (src/mongo/shell/assert.js:6:5)
at assert (src/mongo/shell/assert.js:14:5)
at DBCollection.update (src/mongo/shell/collection.js:220:5)
at (shell):1:10
Any ideas?
Thanks.
First of all if you are trying to update the role field of the profile subdocument your syntax is off. It should be:
db.users.update({_id:"2xnoy3jqcHCaFp7Br"}, {$set: { "profile.role":"admin"}})
Otherwise you will just delete all the other fields of the document.
Regarding the error message, that normally only occurs when you run update with a single argument (the query) without the fields to update. Are you sure you are calling it as documented in your question?
Regardless I would highly advise you to review MongoDB documentation for updates:
http://docs.mongodb.org/manual/tutorial/modify-documents/
Maybe you should try adding ObjectId to the query.
Also, as pointed by #John Petrone you should use $set
I usually do
db.users.update({_id:ObjectId("2xnoy3jqcHCaFp7Br")}, {$set: { "profile.role":"admin"});

mongo db update subdocument - subdocument not in array

I have a document like this,
{
"S" : {
"500209" : {
"total_income" : 38982,
"interest_income" : 1714,
"reported_eps" : 158.76,
"year" : 201303
}
},
"_id" : "pl"
}
I am trying to update this document like this,
{
"S" : {
"500209" : {
"total_income" : 38982,
"interest_income" : 1714,
"reported_eps" : 158.76,
"year" : 201303,
"yield": 1001, <== inserted a new attribute
}
},
"_id" : "pl"
}
I have tried this,
db.my_collection.update({_id: 'pl'},{$set: {'S.500209.yield': 1}})
But I couldn't make it. And I searched in stack overflow and google but I couldn't find out.
I got so many answers but most of them keeping sub-docuemnts in array.
Pleas help me to solve my issue, and please tell me why most of them keeping subdocuments in array.
Number key might cause the problem. Update your field name.
db.my_collection.update({_id: 'pl'},{$set: {'S.a500209.yield': 1}})
EDIT
Upgrade mongo version. It works fine with 2.4.

Mongodb setting a value in an array without .$

I have the query
choices.update({"subchoices.id":'fh3284'},
{$set : { "subchoices.$.name" : "le_new_choice"}}
);
the document:
{ subchoices : [ { "id" : "fh3284", name : "choice1" },
{ "id" : "fh3286", name : "choice2" }
], ... }
Is it possible to rewrite this without using the .$. operator for the (on its own not the one in the $set,$query, etc)? Im using meteor and the client side implementation which doesn't take the .$. yet.
It seems that impossible to do such update withou .$.
I've spent a lot of time to try to sovle it, but couldn't.