pymongo - how to append values to array? - mongodb

I am trying to create a database if it is not there already in mongo, and then create a collection in the database; then insert/update a document (which contains two keys, called erp and dataset whose value is a list of strings) in the collection. I know how to upsert a document like,
self.connection = pymongo.MongoClient(host=db_host, port=db_port)
self.connection.datasets.datasets.update_one({'erp': 'erp1'},
{'$set': {'data_set': ['database1']}},
upsert=True)
When the document is inserted into mongo for the 1st time, create a list with string(s) as values for the field 'data_set', but how to maintain/update the list of strings that whenever a new string comes in, just append the existing list for data_set.
UPDATE.
The working query
connection.erp_datasets.erp_datasets.update_one({'erp_name': 'erp1'},
{'$push': {'data_set': 'database1'}}, upsert=True)

I think what you're looking for a $push update operator.
The $push operator appends a specified value to an array.
self.connection.datasets.datasets.update_one(
{'erp': 'erp1'},
{'$push': {'data_set': 'database1'}}
)

Related

pymongo: searching and editing fields within document

Say i have this database "list", which contains a collection called "users", which contain, among others, an object called "david"
{u'_id': u'david', u'url': u'url3', u'old_url': u'url3', u'wishlist': [[u'Jenara', u'shards', u'nm'], [u'force of will', u'mm2', u'nm'], [u'pact of negation', u'mm', u'nm'], [u'all is dust', u'mm4', u'nm']]}
how can i use pymongo to edit the arrays within the wishlist field? say i want to remove one of the four arrays, or edit one of them?
In order to update an element in an array, use $set. Here is an example - updating the second element and setting it's value to ["something", "else"]:
db.users.update({'_id': 'david'}, {"$set": {"wishlist.1": ["something", "else"]}})
As for the removing an item from an array by index, it's not that easy and straightforward, see:
In mongoDb, how do you remove an array element by its index
How to delete n-th element of array in mongodb

Insert new Documents or modify an array field of existing document

Apologies if this is a re-post, but I wasn't able to quite get the query I want from the mongodb documentation examples.
Here's my issue. I am unable execute in a single query to either update an array_field of an existing document or add a new document and initialize the array_field with an initial value.
I can use findOne() with some conditional logic, and probably solve this, but I would think mongodb has an implementation of this use case
Here's the code so far:
#data_json = JSON document to be added to collection
collection.update_one({"json_id":data_json["json_id"], "_dashbd_id_":dashboard_id},{{"$addToSet": {"array_field":keyword}},{"$setOnInsert":data_json}}, upsert=True)
I'm querying by the json_id, and _dashbd_id_ from my collection. If it exists, then I intend to add the "keyword" to the array_field. If it doesn't exist, create a new document as data_json which include array_field = [keyword]
Any hints and suggestions are appreciated!
If I understood you correctly you want to update values in Database only if they do not exist as well as create new documents with arrays in them. Okay there is a way in mongodb which I will mention in this reply. I think you should know few commands first that will help you achieve similar result (again there is a simple way just read on)
Let me start with the first part:
to update an element in an array you use dot notation to the index example:
db.collection_name.update({"_id": id}, {'$set': {"array_name.indexNumber": value}})
say we have the following document in collection name cars
db.cars.findOne():
{
_id: 1
name: EvolutionX
brand: Mitsubish
year: 2012
mods: [ turbo, headlights ]
}
Say in the above example we want to update headlights with rearlights we do the following (using mongoshell you can drop quotes in key names, Not when using the array index though):
db.cars.update({id:1}, {$set:{"mods.1":"rearlights"}})
1 is the index to headlights.
Note and be careful here that if you did not use index inside of an array like
db.cars.update({id:1}, {$set:{"mods":"rearlights"}})
this will overwrite the existing document _id:1 and it will lose all other attributes or fields inside the document so it will result in the follow:
db.cars.findOne():
{
_id: 1
mods: [ rearlights ]
}
Now, say we want to add an element tires to mods array you can use $push as:
db.collection_name.update({"_id": id}, {'$push': {"array_name": value}})
so it will be
db.cars.update({"_id":1}, {"$push":{"mods":"tires"}})
now say instead of updating mods array you want to remove "headlights". In this case you use $pop
db.cars.update({"_id":1}, {"$pop":{"mods":"headlights"}})
Now with that in mind. The easy way: in mongodb to add to array only if element does not exist you can use $addToSet. I love this operator because it will only add to array if the element does not exist. Here is how to use it:
db.cars.update({"_id":1}, {"$addToSet":{"mods":"headlights"}})
Now if headlights is in the array it will not be added, else it will be added to the end of array.
Okay that is the first part of the question. The second part which is initializing a document with an array. Okay there are two thoughts here: the first is you do not have to. using the addToSet you can create the array if it does not exist as (assuming _id 2 exist but without mods array):
db.cars.update({"_id":2}, {"$addToSet":{"mods":"bonnet"}})
This will create the array if document _id:2 exist. Assuming _id:3 does not exist you will have plug in a third attribute called upsert
db.cars.update({"_id":3}, {"$addToSet":{"mods":"headlights"}}, {upsert:true})
this will create a third document with array mods with headlights inside of it and _id:3. Note though no other attributes will be added only the _id and mods array
the second thought is when you insert a new document you insert it with empty mods array as mod:[]
I hope that helps
suppose your data_json ,dashboard_id and keyword contain following detail.
dashboard_id = ObjectId("5423200e6694ce357ad2a1ac")
keyword = "testingKeyword"
data_json =
{
"json_id":ObjectId("5423200e6694ce357ad2a1ac"),
"item":"EFG222",
"reorder":false,
}
if you execute below query
db.collection_name.update({"json_id":data_json["json_id"], "_dashbd_id_":dashboard_id},{{"$addToSet": {"array_field":keyword}},{ upsert=True})
than it will push keyword to array_field if document exist or it will insert new document with following detail as below.
{
"_id":ObjectId("5sdvsdv6sdv694ce357ad2a1ac"),
"json_id":ObjectId("5423200e6694ce357ad2a1ac"),
"dashboard_id": ObjectId("sddfb6694ce357ad2a1ac")
"item":"EFG222",
"reorder":false,
"array_field":
[
"testingKeyword"
]
}

Error while trying to insert into a collection from an already existing collection in mongoDB

I am using MongoDB 2.6.6
In my database, I have two collections. One is empty, and one with 3000 documents. I would like to skip the first 2000 documents and only insert the last 1000 document from this collection into another one.
The collection containing 3000 documents is called all_events and the empty collection is dates
I used the command:
db.dates.insert(db.all_events.find().skip(2000))
But I got the error:
can't save a DBQuery object at src/mongo/shell/collection.js:143
find() returns a DbCursor object. insert accept DbObject or a list of dbObject as it's first parameter.
use something like:
db.full_set.find(...).forEach(function(e){
db.copy.insert(e);
});

Update not inserting a object in subarray,when upsert=true

I am using mongodb update method with upsert=true.
My data looks like this:
{"my_id":"1",
"test_list":[{"test_id":1,"test_name":"pppp"}]}
now I am using the following command:
db.testcol.update({"my_id":1,"test_list.test_id":2},{"$set":{"test_list.$.test_name":"mmmm"}},true,true)
Now I want a new object inserted into the "test_list" as it does not exist
but I am getting the error:
Cannot apply the positional operator without a corresponding query field containing an array.
I cannot use "insert" for my operation, as I dont know whether the data is their and the field needs to be updated,or its not their and needs to be inserted(for the first time)
Upserts are for when you want the update to work whether the entire document is there or not, not just an array element. For the array element case you can use $addToSet:
db.testcol.update(
{"my_id": "1"},
{"$addToSet": {"test_list": {"test_id": 2, "test_name": "mmmm"}}})
It will only add the new element to the doc's test_list array field if a matching element isn't already present.

MongoDB alter field

I have an collection "companies" and the documents have this structure:
id, name, address, branch, city
I want to add an keyword field that will have an index, so I can do a fulltext search, but how can I add a field to each document?
Thanks for help
There's no schema in MongoDB, so you don't have to add a field to every document.
Just start writing new documents with this field, or update old documents when you have this value for them.
As for indexing, now you can leverage sparse indexes, they will be more efficient if most of your documents don't have this field.
Also, you might want this keyword field to be an array. It can be handled more efficiently than a string.
If you want to add a field with the same value to all documents in a collection, you can use this:
db.collection.update({}, // update all documents
{$set : {keyword : []}}, // or another value
false, // is upsert?
true) // is multi-update?
When you do a $set, you can't use values from other fields. So if this new value is going to be a function of other fields, you have no other option, but to loop through the documents and update them one by one.