prevent duplicates of multiplefields with index - mongodb

My document:
{
"age":"20",
"name":"leandro"
}
I need prevent inserting new documents if another exists with same age and email.
Can I do this using index?

Yes you can do it by creating index with unique=true as follows. After creating index, if you try to insert a document with same age & name then you will get duplicate key exception.
db.myObject.ensureIndex({age:1, name:1}, {unique : true})
For details you can read Create a Unique Index document.

Related

mongo_connector.errors.OperationFailed: insertDocument :: caused by :: 11000 E11000 duplicate key error index

I have an existing python method which is doing the update operation properly in mongodb. I got a requirement where if any document modified in mongodb, I need to create a new document in same collection for audit purpose. So I added below piece of code under existing method to perform insert operation.
self.mongo[db][coll].insert(update_spec)
As i'm passing same ObjectId of existing document to my insert operation its failing with below exception,
mongo_connector.errors.OperationFailed: insertDocument :: caused by :: 11000 E11000 duplicate key error index: mongotest1.test.$_id_ dup key: { : ObjectId('57dc1ef45cc819b6645af91d') }
Is there a way to ignore the ObjectId of existing document, so that I can insert the other existing values in my new inserted document? Kindly suggest. Below is the complete code.
def update(self, document_id, update_spec, namespace, timestamp):
"""Apply updates given in update_spec to the document whose id
matches that of doc.
"""
db, coll = self._db_and_collection(namespace
self.mongo[db][coll].insert(update_spec)
self.meta_database[meta_collection_name].replace_one(
{self.id_field: document_id, "ns": namespace},
{self.id_field: document_id,
"_ts": timestamp,
"ns": namespace},
upsert=True)
no_obj_error = "No matching object found"
updated = self.mongo[db].command(
SON([('findAndModify', coll),
('query', {'_id': document_id}),
('update', update_spec),
('new', True)]),
allowable_errors=[no_obj_error])['value']
return updated
Delete the id field from the update_spec object before inserting. The specific way to do this depends on which field of update_spec is the id, and what object type it is.

Update an array using Jongo

I have a mongodb collection of the form
{
"_id":"id",
"userEmail":"userEmailFromCustomerCollection",
"customerFavs":[
"www.xyz.com",
"www.xyz.com",
"www.xyz.com"
]
}
I need to add an element to the customers favs array using Jongo , I am using the following code snippet to do so .
String query = "{userEmail:'"+emailId+"'}";
customerFavCollection.update(query).with("{$addToSet:{customerFavs:#}}", favUrl);
My problem , is that I need to upsert the document if the document does not
exist already , how can I do so using Jongo, I know an easier option would be to retrieve the document by Id and if it does not exist then insert the document using save() , but I am trying to avoid the extra retrieve.
You can add upsert() on the query.
customerFavCollection.update("userEmail:#", emailId)
.with("{$addToSet:{customerFavs:#}}", favUrl)
.upsert();

Search for ObjectId of a document: pymongo

I want to access a document in collection by 'name' attribute for getting its ObjectId so that i can insert that unique objectid to other document for reference.
cursorObject = db.collectionIngredient.find({'name': 'sugar'})
I want _id field of cursorObject.
cursorObject.'_id' or cursorObject._id not working.
I have tried __getitem__, __getattribute__ and so much internet surfing but couldn't able to find a way.
Please help
First, as #jjmartinez pointed out, find returns a cursor, which you need to iterate over, in order to get hold of the documents returned by your query. The _id field belongs to the documents, not the cursor.
I'm guessing that in your case the name is unique, so you can avoid cursor/iterating if you use find_one instead of find. Then you get the document directly.
Then, to access the _id, you just need a standard dict-item access:
id = doc['_id']
So we get:
ingredient = db.collectionIngredient.find_one({'name': 'sugar'})
if ingredient is not None:
id = ingredient['_id']
else:
id = None
When you do cursorObject = db.collectionIngredient.find({'name': 'sugar'}) you have a collection of documents, not a single element. So you need to explore all the collection. You need to iterate inside the cursor:
try:
cursorObject = db.collectionIngredient.find({'name': 'sugar'})
except:
print "Unexpected error:", sys.exc_info()[0]
for doc in cursorObject:
print doc
Here you have the Pymongo Tutorial

Multi level MongoDB object querying by key

If you only know the key name (say "nickname"), but not the exact path to that key in the object.
e.g. nickname may be at the first level like:
{"nickname":"Howie"}
or at the second level:
{"user":{"nickname":"Howie"}}
Is it possible to query for nickname equal "Howie" that would return both documents?
Unfortunately there is no wild card that allows you to search for a field at any level in the db. If the position is not relevant and you can modify the document structure you have 2 choices here. You can store your document as
{ fieldname:"nickname", value : "Howie" }
{ fieldname:"user/nickname", value: "Howie" }
You can then query using
db.so.find({fieldname:/nickname/, value:"Howie"})
Alternatively you can store as
db.so.insert({value:"Howie", fieldpath:["nickname"]})
db.so.insert({value:"Howie", fieldpath:["user", "nickname"]})
The advantage with the second approach is that you can now index {fieldpath:1, value:1} and a query on it such as
db.so.find({fieldpath:"nickname", value:"Howie"})
will be an indexed query.

How do you clone ( duplicate ) a MongoDB object in a collection of the same db?

I need to duplicate (clone) an object in the collection via dbshell. Having something like this :
> db.users.distinct( 'nickname' )
[
"user1",
"user2",
"user3",
"user4"
]
>
where user1 select a complex object in users collection, how can I duplicate the object then change (rename) user1 field in userX ?
Code
> user = db.users.findOne({'nickname': 'user1'})
> user.nickname = 'userX'
> delete user['_id']
> db.users.insert(user)
Description
You need to find user object and put it into the variable. Than you need to modify the property you want and than you need to insert the whole object as new one. To achieve that you need to delete _id property that the object already has. And than just use insert to create the new one.
Do not delete the _id property; for some reason some values lose their type. For example, integers are converted to doubles.
Use this solution:
var user = db.users.findOne(...)
user._id = new ObjectId()
// set other properties
db.users.insert(user)
The _id field is a required field and we can't delete it like that. What I do is call toJSON() to the returned object and then delete the _id.
var rObject = dbObject.toJSON();
delete rObject._id;
db.insert(rObject);