I clearly don't understand how I update / insert a subdocument in an existing document.
I tried the following:
query = aCollection.find_one({stuffToFind})
aCollection.update(query,
{"$set": {"subDoc" : {"1" : String, "2" : datetime.datetime.now(), "3" : otherString}}})
this only works one time but I want to constantly change the subDoc's Data 1,2 and 3 if this code is executed. find_and_modify also fails, because it seems to overwrite the whole document deleting all other fields but the id and those specified in update.
Since I'm pretty new to MongoDB it would be nice if someone could give me a code example how to figure out my problem.
Edit: without the "$set" statement it remains unchanged as well on a second execution..
Edit2: this seems to work, eventhough I'm unable to edit the affected (JSON)document directly in MonjaDB anymore :D
aCollection.update(query(but this time not as a variable),
{"$set" : {"subDoc.1" : Sting, "subDoc.2" : datetime.datetime.now(), "subDoc.3" : otherString}})
I dont know, why this is working so maybe someone could explain what I did wrong..
Thanks in advance,
Codehai
The query you supply to update in the first example is not correct, instead of:
query = aCollection.find_one({stuffToFind})
you should have:
query = {stuffToFind}
The reason that the update does not throw an error is that the result of find_one is a dictionary. Note also that sometimes the above will even work since in the update you are actually asking MongoDB to match the whole document that corresponds to the initial
query. Subsequent uses of query of course in that case will not bring the expected results since the document will have been changed from the update.
The $set updates only the keys that we specify leaving everything else untouched. That means that if we update an embedded object then the whole embedded object will get replaced with what we specify in $set. If we want to pinpoint keys in the embedded object
we must use dot notation as you do in the second example.
Related
I'm using mongodb v4.0.3, and this happens both with the shell and in compass.
This only happens with a certain collection. It previously had overriden ids (instead of the default mongodb id, there was a string. I dropped the collection and I recreated it without that).
I have the following structure ("mystructure"), for example:
{
"_id":ObjectId("5bd44eb528d61e3374b5e6ea"),
"custom_field":"data",
}
When I query it without a filter it returns all the docs:
db.mystructure.find({});
When I search for its objectid, it returns properly
db.mystructure.find( {"_id": ObjectId("5bd44eb528d61e3374b5e6ea")} );
But when I try to filter with any field, it doesn't return anything
db.mystructure.find( {"custom_field": "data"} );
At first I thought it would be solved recreating the collection with the automatically generated ids from mongodb but the problem persists. There are no "hidden" spaces in the string or anything like that. The same query in compass isn't working either. Other collections do work. It's on the same db, with the same user.
Why can this be?
Thank you very much.
you should write below code where 62c01e5a763d106152a2e53f is your _id
{_id:ObjectId('62c01e5a763d106152a2e53f')}
As the Title suggests, I found a rather strange behavior which I am not sure to attribute to Studio3T or to MongoDB.
I have a collection containing simple documents, as follows:
Example of a document in the collection
Whenever I perform a query using the query builder, everything works as expected. However, when I do it using IntelliShell or Aggregate AND if such query is based on the field StudyID, no document is returned, regardless the query.
For example, the two following queries return, respectively, an empty list and no documents.
db.Cortisol.distinct("StudyID")
db.Cortisol.find({},{"StudyID" : 1})
While the following very similar query returns the documents, as expected.
db.Cortisol.find({},{"ExamID" : 1})
As you can see the queries are correct, I did not misspell anything so does anyone have a possible explanation for such a strange behavior?
I wonder if your field "StudyID" contains some weird (invisible) unicode chars. This would explain why dragging the field into query builder works (because the query builder uses the exact same string) and typing S-t-u-d-y-I-D doesn't.
When you run an empty query and you see documents with StudyID returned, can you then copy the field name of your StudyID field to the clipboard, and then when you type your query in IntelliShell paste the StudyID name?
I have a dictionary. I need to insert column 2 into mongodb corresponding to column 1(key).
Say this is the dictionary:
values = {'a':['1','2','3'],
'b':['1','2'],
'c':['3','4'] }
Right now I am doing this:
for k,v in values.items():
col4.update({"name":k},{"$set":{"fieldName":v}})
But this takes 3 accesses to the db. Is it possible to do it one go like the way $in works.
In your code you are finding each document by name field and set its fieldName to v. There is no update operation in Mongo that can do such thing in one shot for multiple documents.
However there is a bulk insert statement which can be more efficient than multiple inserts or updates. http://docs.mongodb.org/manual/core/bulk-inserts/.
I thinks I previously didn't quite understand what you were asking and wrote the answer below, but I'm still not sure what you mean by $in. Perhaps you can provide example of data before and after update in DB, that way it will be absolutely clear what you are trying to achieve.
OLD answer ... (I'll edit it soon)
You need to restructure your loop. Build up a query (not running) by adding {field: newValue} to $set clause. After the loop is done you will have an analog of {$set:{"a": 1, "b": 1, "c": 3}}. Then you will update all fields in one shot.
Here is official documentation:
http://docs.mongodb.org/manual/reference/operator/update/set/
I use mongo_insert() three times to insert my data in three different collections. The problem is that the "_id" field must be exactly the same in each of the collections, but I do not know how to (ideally) recover and reuse the "_id" field generated in my first mongo_insert...
Please, advice me how to do it.
Normally, you could have different field, like CustomId for your private needs, and leave _id for mongo generation.
But if you still need it to be exactly the same - there could be 2 variants:
1) setting custom generated _id do each doc.
2) Save first doc, then read it again, check it's _id and set it to the other docs.
While I undertand a foreign key constraint would not make sense for a NoSql database, should it not ensure that it updates the indexes if it allows me to rename fields?
http://www.mongodb.org/display/DOCS/Updating#Updating-%24rename
{ $rename : { old_field_name : new_field_name } }
but if I had
db.mycollections.ensureIndex({old_field_name:1});
wouldn't it be great if the index was updated automatically?
Is it that since system.indexes is simply just another table and such a automatic update would imply a foreign key constraint of sorts, the index update is not done? Or am I missing certain flags?
It doesn't do it.
The answer to your question "wouldn't it be great if the index was updated automatically?" is, "no, not really".
If you think that renaming fields is a good idea you can add the new index yourself at the same time. You'll likely have lots of other changes to do in your code to reflect a rename on a field (queries, updates, map reduce operations, ...) so why do you think it should single out index recreation as something that should happen automatically on what is a very rare operation when it's just one thing out of many that you'd need to do, manually?
If you care about this feature, go request it, 10Gen are incredibly responsive to suggestions, but I wouldn't be surprised if the answer was "why is this important?"
Quoting Mike O' Brien:
The $rename operator is analogous to doing a $set/$unset in a single atomic operation. It's a shortcut for situations where you need to take a value and move it into another field, without the need to do it in 2 steps (one to fetch the value of the field, another to set the new one).
Doing a $rename does mean the data is changing. If I use $rename to rename a field named "x" to "y", but the field named "y" already existed in the document, the old value for "y" is overwritten, and the field "x" will no longer exist anymore. If either "x" or "y" is indexed, then the operation will update those indexes to reflect the final values resulting from the operation. The same applies when using rename to move a field from within an embedded document up to the top level (e.g. renaming "a.b" to "c") or vice versa.
The behavior suggested in the SO question (i.e., renaming a field maintains the relationship between the field it was moved to and its value in the index) then things can get really confusing and make it difficult to reason about what the "correct" expected behavior is for certain operations. For example, if I create an index on field "A" in a collection, rename "A" to "B" in one of the documents, and then do things like:
update({"A" : }, {"$set":{"B":}}) // find a document where A= and set its value of B to
update({"B" : }, {"$set":{"A":}}) // find a document where B= and set its value of A to
Should these be equivalent?
In general, having the database maintain indexes across a collection by field name is a design decision that keeps behavior predictable and simple.