Error getting MongoDB by _Id in Flask - mongodb

I can query my MongoDB and I see the "_id" value like this:
"_id" : BinData(3,"sFgVQWMKzUiWl5dql62j2g==")
Using Flask 0.10.1 and PyMongo 3.0.3 I attempt to "find_one" like this:
record = db.collection.find_one({'_id': ObjectId("sFgVQWMKzUiWl5dql62j2g==")})
And I get this error:
bson.errors.InvalidId: 'sFgVQWMKzUiWl5dql62j2g==' is not a valid ObjectId, it must be a 12-byte input or a 24-character hex string
Any help would be appreciated.

Try this:
record = db.collection.find_one({'_id': BinData(3, "sFgVQWMKzUiWl5dql62j2g==")})

Ok here is how I got this working. From my PyMongo client I queried the result and got this:
_id: "497ffaf0-5ed3-3a4e-99ae-6b5c5f9b431e"
Note how that is not like the MongoDB console client which returns this:
_id : BinData(3,"sFgVQWMKzUiWl5dql62j2g==")
So seeing that the value looked like a GUID I started digging around and found that is a UUID and with that I did this:
import uuid
record = db.collection.find_one({'_id': uuid.UUID("497ffaf0-5ed3-3a4e-99ae-6b5c5f9b431e")})
This worked! Hazzah.

You are storing _id as bindata and trying to retrive it as ObjectId,
instead of ObjectId.
First you need to convert your base64string to binary and then try to search.
bi = binary.Binary("sFgVQWMKzUiWl5dql62j2g==");
record = db.collection.find_one({'_id': bi});
This will work for you.
It will convert your id to binary then compare to get result.

Using Flask, MongoEngine I also was receiving errors searching by _id: mongoengine.errors.ValidationError: "DBRef('m_turk', ObjectId('5966b478b929570647f51a5c'))" is not a valid ObjectId, it must be a 12-byte input or a 24-character hex string
In my case, the object id from MongoEngine.Document is of type bson.dbref.DBREF, whereas MongoEngine.Document expects type bson.objectid.ObjectId, despite returning bson.dbref.DBREF on MongoEngine.Document.objects(...).*. I'm not sure if this is an API inconsistency or simply my fault.
The fix was:
from flask_mongoengine import MongoEngine
from bson.objectid import ObjectId
... set Flask up ...
db = MongoEnginee(app)
class MiniFoo(db.Document):
foo = db.StringField()
class MyDoc(db.Docment):
key = db.StringField()
myself = db.ReferenceField(MiniFoo)
other_foos = db.ReferenceField(MiniFoo)
myobj = MyDoc.objects.get(key="over the rainbow")
# want to find other foos!
# Will fail with exception above
try:
MiniFoo.objects.with_id(myobj.other_foos[0].id)
except:
MiniFoo.objects.with_id(ObjectId(obj.id))

with MongoEngine
from flask_mongoengine import MongoEngine
from bson.objectid import ObjectId
db = MongoEngine()
db.init_app(app)
class Model(db.Document):
_id = db.ObjectIdField()
name = db.StringField(required=True)
#classmethod
def findById(cls, _id: str):
return cls.objects(_id=ObjectId(_id)).first()
modelById = Model.findById('601ec2d13ad7559bf7ebad76')

Related

how to find item in mongo collection when _id is object?

I have mongo collection which have _id key as object of 2 key value pair. (_id = {"id":123, "slice":1}). how can I use pymongo find() to fetch an item using _id? sample collection item looks like this.
Use the uuid module as follows:
db.foo.drop()
import uuid
uu = uuid.uuid4()
uu2 = uuid.uuid4()
db.foo.insert_one({'_id':{'execution_id':uu, 'slice':1}, 'realm':'bar'})
print("should find it:", db.foo.find_one({'_id':{'execution_id':uu, 'slice':1}}))
print("should NOT find it:", db.foo.find_one({'_id':{'execution_id':uu2, 'slice':1}}))

How to set a default value to server generated time?

Is is possible to have a datetime field which has as a default server generated time during save?
class ADoc(Document):
...
created_at = me.DateTimeField(default=datetime.datetime.utcnow)
This model has two issues:
created_at will get a value during model instance creation, not the time when the document is saved into the database.
Client time is used, which might differ from the server time -- I'd like to always use server time as the time source.
Maybe you can use the operator $currentDate ?
UPD:
I like pymongo, but I think that can be for MongoEngine, you can try:
collection = Animal._get_collection()
collection.update({}, {"$currentDate": {"date": 1}}, upsert=true)
example here
By default the _id field contains the timestamp on creation.
You can access it like this ObjectId("507c7f79bcf86cd7994f6c0e").getTimestamp().
There's also $currentDate and new Date.
I would use defined by me insert method in my ADoc class:
from datetime import datetime
class ADoc:
def __init__(self, db, config):
self.docs= db['docs']
self.config = config
def insert(self, document):
item = {
'name': document['name'],
'created': datetime.utcnow()
}
self.docs.insert_one(item)
then simply execute the method when needed
client = MongoClient(DB_URL)
db = client['yourDb']
doc = "your new doc"
adoc = ADoc(db, app.config)
adoc.insert(doc)

Error writing shell script in python for mongodb In case of userid call

cursor2 = db.BrandScoreHistoryUpdateFinal.find(
{"UserOid" :ObjectId("55d6e7c0f0639509b4c7a83b")}).count()
It should return the count of userid for that particular value but its poping out the error as
Name Error: name objectid is not defined.
when I tried to use :
ObjectId("55d6e7c0f0639509b4c7a83b").toString()
cursor2 = db.BrandScoreHistoryUpdateFinal.find(
{"UserOid" :ObjectId("55d6e7c0f0639509b4c7a83b")}).count()
I have the same error
To query your document you need to import ObjectId
from bson.objectid import ObjectId
Also the best way to do this is:
ursor2 = db.BrandScoreHistoryUpdateFinal.count(
{"UserOid": ObjectId("55d6e7c0f0639509b4c7a83b")})

How do I find a document using Mongolab's $oid with pymongo?

I'm trying to do this:
event = coll.find_one({"_id": {"$oid": event_id}})
Where event_id is the string from an ObjectId:
event_id='50bbd48eefbdd2a1e83bc440'
but the event ends up empty. I'm certain this is not how you find documents with the ObjectId's in pymongo, but I have searched for a while and have not figured out how. Any help would be appreciated. Thanks!
You have to convert event_id to an ObjectId like this:
from bson.objectid import ObjectId
event_id='50bbd48eefbdd2a1e83bc440'
event = coll.find_one({"_id": ObjectId(event_id)})
When searching by id with event_id the ObjectId string as you define it, simply do
event = coll.find_one(event_id)

How to get the object id in PyMongo after an insert?

I'm doing a simple insert into Mongo...
db.notes.insert({ title: "title", details: "note details"})
After the note document is inserted, I need to get the object id immediately. The result that comes back from the insert has some basic info regarding connection and errors, but no document and field info.
I found some info about using the update() function with upsert=true, I'm just not sure if that's the right way to go, I have not yet tried it.
One of the cool things about MongoDB is that the ids are generated client side.
This means you don't even have to ask the server what the id was, because you told it what to save in the first place. Using pymongo the return value of an insert will be the object id. Check it out:
>>> import pymongo
>>> collection = pymongo.Connection()['test']['tyler']
>>> _id = collection.insert({"name": "tyler"})
>>> print _id.inserted_id
4f0b2f55096f7622f6000000
The answer from Tyler does not work for me.
Using _id.inserted_id works
>>> import pymongo
>>> collection = pymongo.Connection()['test']['tyler']
>>> _id = collection.insert({"name": "tyler"})
>>> print(_id)
<pymongo.results.InsertOneResult object at 0x0A7EABCD>
>>> print(_id.inserted_id)
5acf02400000000968ba447f
It's better to use insert_one() or insert_many() instead of insert(). Those two are for the newer version. You can use inserted_id to get the id.
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
myDB = myclient["myDB"]
userTable = myDB["Users"]
userDict={"name": "tyler"}
_id = userTable.insert_one(userDict).inserted_id
print(_id)
Or
result = userTable.insert_one(userDict)
print(result.inserted_id)
print(result.acknowledged)
If you need to use insert(), you should write like the lines below
_id = userTable.insert(userDict)
print(_id)
Newer PyMongo versions depreciate insert, and instead insert_one or insert_many should be used. These functions return a pymongo.results.InsertOneResult or pymongo.results.InsertManyResult object.
With these objects you can use the .inserted_id and .inserted_ids properties respectively to get the inserted object ids.
See this link for more info on insert_one and insert_many and this link for more info on pymongo.results.InsertOneResult.
updated; removed previous because it wasn't correct
It looks like you can also do it with db.notes.save(...), which returns the _id after it performs the insert.
See for more info:
http://api.mongodb.org/python/current/api/pymongo/collection.html
some_var = db.notes.insert({ title: "title", details: "note details"})
print(some_var.inserted_id)
You just need to assigne it to some variable:
someVar = db.notes.insert({ title: "title", details: "note details"})
To get the ID after an Insert in Python, just do like this:
doc = db.notes.insert({ title: "title", details: "note details"})
return str(doc.inserted_id) # This is to convert the ObjectID (type of doc.inserted_id into string)