How to search document by oid in mongoengine - python

I need get documents from db by oid, like:
Docs.objects(_id='4f4381f4e779897a2c000009')
But how to do it, if _id requires ObjectId object and even I try to set ObjectId from pymongo it doesn't work.
Docs.objects(_id=pymongo.objectid.ObjectId('4f4381f4e779897a2c000009'))
return empty list

This should work:
Docs.objects(pk='4f4381f4e779897a2c000009')

How about just using the raw string:
Docs.objects.get(id='4f4381f4e779897a2c000009')
That is probably the easiest way ... right ?

Came to this question because I had a lot of trouble with this myself. It seems like PyMongo changed this and objectid is no longer inside pymongo and is now instead:
import bson
Doc.objects.get(id=bson.objectid.ObjectId('4f4381f4e779897a2c000009'))
Also, Mongoengine uses the name 'id' for the ObjectID field.

This thread is old, but in case someone looks at it around 2022:
This works fine with MongoDB Atlas + Mongoengine == 0.23.1
from bson.objectid import ObjectId
Doc.objects(_id=ObjectId("85a2c854002c893dd7756b5g"))

Related

Pymongo query to get the latest document from the collection in Mongodb using Python

I am using pymongo and have below query to get the documents from a collection:
coll_employee = db.get_collection('employeeDetails')
query1 = [{'$match': {'EmployeeId': ObjectId('5edde542f6468910e080e462')}}]
document = coll_employee.aggregate(query1)
tmp1_list = []
for i in document:
tmp1_list.append(i)
print(tmp1_list)
I am making a query based on EmployeeId which is an ObjectId. Running above code, I am getting all the documents of the collection. Is there any way we can only get the latest document which was created. Please help. Thanks
Hi you can do a sort by ObjectID ( -1 ) if you want the latest record and then use the limit operation to retrieve just the first record .
It's like running the following query on your collection
db.coll_employee.select({'$match': {'EmployeeId': ObjectId('5edde542f6468910e080e462')}}).sort('_id':-1).limit(1)
PyMongo's syntax is little bit different than Mongo Shell's syntax. You don't need to use aggregation for this, a simple find() method will can do the work along with sort() and limit() methods. Below query will be helpful:
db.coll_employee.find().sort('_id',-1).limit(1)
You can use any field, which gets incremented as we insert, like you were saying in comments, you have created field. So, instead of _id, you can use this field.
Here is the solution which worked for me:
query1 = {'EmployeeId': ObjectId('5edde542f6468910e080e462')}
document = coll_employee.find(query1).sort('_id', 1).limit(1)

How to query for objectid on mongodb using python

I am trying to print all the object ids in a collection I have in mongoDB. I understand how to convert the ObjectId to a string, however I am not sure how to actually make a call to list all the object ids.
I tried the following from pymongo documentation but nothing happens because I have 4 ObjectIds
def get(post_id):
Document=client.db.collection.find_one({'_id':ObjectId(post_id)})
return Document
from bson import ObjectId
id = "5fec2c0b348df9f22156cc07"
objInstance = ObjectId(id)
collection.find_one({"_id": objInstance})
# below line works same as the above
collection.find_one({"_id": ObjectId(id)})
collection.find_one(ObjectId(id))
bson should already been installed once you installed pymongo

PyMongo find_one() returns nothing when passed _id as query parameter

I have a single document in my Mongo database:
{"_id" : ObjectId("569bbe3a65193cde93ce7092"),
"categories" : [{_id: 0, "category": "Groceries"},
{_id: 1, "category": "Bills"}, . . .]}
Using PyMongo in my project, I get this result calling find_one():
x = db.collection.find_one({"_id": "ObjectId(\"569bbe3a65193cde93ce7092\")"})
print(x)
// None
Whenever I perform this same query in the Mongo shell, it returns my document. I cannot for the life of me figure out why this is not working. Using find({}) returns the document, so I know PyMongo can see it.
I can call find_one({"categories": {"$exists": True}}) to retrieve the document, and since this will be the only document containing "categories", this will work; however, now I'm just baffled as to why accessing the document by _id is giving me such trouble. Neither escaping the quotes nor quote-wrapping 569bbe3a65193cde93ce7092 has made any difference.
To add to the #Simulant answer, you need to import the ObjectId from the bson.objectid:
from bson.objectid import ObjectId
x = db.collection.find_one({"_id": ObjectId("569bbe3a65193cde93ce7092")})
pass it without the quotes on the content of _id you also need to import ObjectId.
from bson.objectid import ObjectId
{"_id": ObjectId("569bbe3a65193cde93ce7092")}
If you pass it with quotes you are searching for an Object with the String ObjectId("569bbe3a65193cde93ce7092") as ID. But in MongoDB the ID is an Object and not a String. Thats a difference.

django orm group by json key in json field

I'm using json field on my django model:
class JsonTable(models.Model):
data = JSONField()
type = models.IntegerField()
I tried next query, which works for normal sql fields:
JsonTable.objects.filter(type=1).values('type').annotate(Avg('data__superkey'))
But this throws next error:
FieldError: Cannot resolve keyword 'superkey' into field. Join on 'data' not permitted.
Is there way to make group by on json key, using Django ORM or some python lib, without use of raw sql?
Versions: Django 1.9b, PostgreSQL 9.4
UPDATE
Example 2:
JsonTable.objects.filter(type=1).values('data__happykey').annotate(Avg('data_superkey'))
throws same error on happykey
After some researching I found next solution:
from django.db.models import Count
from django.contrib.postgres.fields.jsonb import KeyTextTransform
superkey = KeyTextTransform('superkey', 'data')
table_items = JsonTable.objects.annotate(superkey = superkey).values('superkey').annotate(Count('id')).order_by()
I did not sure about order_by(), but documentation says that is needed.
For another aggregation function type casting needed:
from django.db.models import IntegerField
from django.db.models.functions import Cast
superkey = Cast(KeyTextTransform('superkey', 'data'), IntegerField())
I test with another model, hope that write this code without misprints. PostgreSQL 9.6, Django 2.07
If you are using this package https://github.com/bradjasper/django-jsonfield,
there is nothing in the code for managing such simulated related queries (data__some_json_key)
As Json data is text, you will have to go to raw sql or better : use queryset extra() method, but parsing Json in sql seems to be difficult.

how can I get a valid object id of mongodb from a string?

I want to make my mongodb OjectId to a field:
class ZhinengStats(Document):
zhineng_id = ObjectIdField(db_field="_id", primary_key=True, required=True, help_text="job id")
but a valid ObjectId must be a 12-byte input of type 'str' or a 24-character hex string, so if I do this:
ZhinengStats.objects(zhineng_id="programmer").first()
I will get an error. I thought a hash is a good way:
hash("programmer") # 7354308922443094682
but as you can see, hash seems not ok.
So how can I get a valid object id?
UPDATE:
the main problem is because this is field is a chinese, so something like this:ObjectId('兼职'.decode("utf-8")) can not work, so how can I make this support utf-8?
Is there any reason why you must generate the ObjectId from a string? If you simply wants an unique id for your mongodb document, you can generate one automatically like so
from bson.objectid import ObjectId
_id = ObjectId()
the ObjectId generated will be based on the machine's hardware signature, and the current time
Python mongodb documentation has examples ready for you:
class bson.objectid.ObjectId(oid=None)
Initialize a new ObjectId.
ObjectId(b'foo-bar-quux')
ObjectId('666f6f2d6261722d71757578')
Assuming the string is in variable rndId, do the following:
from bson.objectid import ObjectId
rndId="1234"
collection.find_one({"_id": ObjectId(rndId)
*** Pre-install the bson package dependency :
> pip install bson

Categories