How to define objectid in EmbeddedDocument with mongoengine? - mongodb

My document has some EmbeddedDocumentList and each of EmbeddedDocument should have autogenerated ObjectId(like _id) field because I will write query to get single EmbeddedDocument with this _id field.
How to reach that?

Basically you can do it with following code
from mongoengine import *
from bson.objectid import ObjectId
class MyEmbeddedDocument(EmbeddedDocument):
oid = ObjectIdField(required=True, default=ObjectId,
unique=True, primary_key=True)
...
class MyDocument(Document):
embedded_list = EmbeddedDocumentListField(MyEmbeddedDocument)
...
Let explain more,
According to documentation you can add ObjectIdField to your models however it is not required and primary_key then you should set this attribute as True. Also, it do not generate ObjectId for each of it then import and set default it as ObjectId.
Last step is little bit tricky. If it is required explain,
bson.objectid.ObjectId is class that generate new objectids.
Moreover documentation say that default value can be callable than that explain clearly how it is work.
Also name of _id for embeddeddocument is not best naming practise beacuse you will write query for embeddeddocument with duble underscore and '_id' name have one more underscore as following code
MyDocument.objects.get(notice___id)
Then mongoengine throws exception beacuse of '_id' name have one more underscore. Thus you should give name as 'oid' as a short version of objectId or renname 'id' directly or what you want.

Related

Are custom _id fields in MongoDB still of type ObjectId

I'm building a project with MongoDB, but I'm a little bit confused on how the _id field works. My understanding is that, by default, MongoDB will generate an object of type ObjectId and assign it as the id.
However, in my server, I'm assigning an arbitrary string as the _id of an object. What I haven't quite understood yet: Is this string somehow converted to an ObjectId, or does the type of the _id field change to string?
MongoDB will generate an _id field with an ObjectId value if an _id field does not exist in the document. If you create the _id by your own, then you can use whatever datatype you like to use. MongoDB does not modify it.
The only constraint is, it must be a unique value.

How do you use MongoDB/bson in repository pattern

Good morning,
I'm currently trying to build a REST-API project for learning purposes and want to use the repository pattern as practice.
I have a model module where I define structs to use. Like user and posts (for both I have set the ID to a string). MongoDB uses ObjectIDs as IDs though. So my current solution is converting that in the MongoDB repository awkwardly to a user/post-struct using that ObjectID and then back again to the user/post-model that the rest of the program is using.
Is there a better way to achieve that same thing without awkward struct conversions?
Here is the code for that:
https://github.com/schattenbrot/mini-blog-api
Thanks in advance already for any ideas and tips I can try out.
Mongo uses the field _id as an object's id. When you insert a document without this field, mongo auto generates its own object id which is what is happening in your case. The solution is to insert your struct with the ID field marked as _id.
This can be done by adding a bson tag on your struct with _id. Mongo will use your id instead of generating one on its own. When you marshal to json, the bson tag is ignored so everything else in your application stays the same.
type Post struct {
ID string `json:"id,omitempty" bson:"_id"`
Title string `json:"title,omitempty" validate:"omitempty,min=3,max=40"`
Text string `json:"text,omitempty" validate:"omitempty,min=5,max=700"`
Creator string `json:"user,omitempty" validate:"omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
}

Put a prefix for ObjectID for MongoDB _id field

I'm trying to put a prefix before the auto generated _id, to identify from which collection came an id, but I still want to use the mongo unique id generator.
So I can know that this id model_5e1a51821c9d44000089e3e0 came from the Model collection.
Is there a solution for that without messing with random string ?
Edit
The _id need to be string castable, since I use it as id in a graphQL object. I need to differentiate ids because I use an union in my schema and resolver need to know in which table to find the data.
The _id can be generated within an application with the constructor ObjectId(). If you want to add a prefix for the generated field, you can use an embedded document as a field for the _id, like this:
_id: {
idPrefix: "Model",
_id: ObjectId("5e1bd112b7f18a490a4bafb5")
}
Other way of identifying if a document is from another collection is use a separate boolean field:
{
_id: ObjectId("5e1bd112b7f18a490a4bafb5"),
isFromModel: <boolean true or false>,
...
}
There are some options available to do this, I'm just trying to tell you the way how would I do if I need this.
Step 1: You can generate the document and it will return you ObjectId (_id) .
Step 2: Take that value and prefix it with model like this.
let _id=5e1a51821c9d44000089e3e0;let new_idValue="model_"+_id;
Step3: Now update your document by _id and push new value in place of if as
this.db.document.findByIdAndUpdate(_id,{$set:{{_id:new_idValue}})
This is what you can do. If you find some best solution than mine, let me know as well. I will highly appreciate.

Can't find documents by criteria containing string objectId value

I have a collection list such:
{username: 'somename',
friendId: '57d725d6b8b144044602bf74' <-- This a reference objectId to another doc
}
When I query docs in my collection with criteria {friendId : '57d725d6b8b144044602bf74'} I get no results back .
Any other field query works fine.
I tried to convert the value to ObjectId('57d725d6b8b144044602bf74') even though the value is just a string, still no go.
Why am I failing to search for by that type of string ?
you are trying to achieve 'self-join' in mongoDB and you seems to rely on the _id field generated by mongodb.
i would suggest you to supply custom _ID fields to the document.
eg:
{_id:"alex", name:"alex", friendID:""}
{_id"john", name"john", friendID:"alex"}
and then you can execute your queries with ease on friendID field. Give it a shot and see if this make sense for your requirement.

MongoDB Grails plugin ObjectId V.S. String id

I have a question about MongoDB id for grails. I used String id in domain class, it would create string id in domain class which is fine. But when I insert entries in mongodb mannually(run db.Things.insert()), it would create an ObjectId(which is not String) for the new entry, I wonder how we could resolve this issues.
thanks!
Refrence from: Mongo Collections - Reference Documentation
By default in GORM entities are supplied with an integer-based
identifier. So for example the following entity: class Person {} Has
a property called id of type java.lang.Long. In this case GORM for
Mongo will generate a sequence based identifier using the technique
described in the Mongo documentation on Atomic operations.
However, sequence based integer identifiers are not ideal for
environments that require sharding (one of the nicer features of
Mongo). Hence it is generally advised to use either String based ids:
class Person {
String id } Or a native BSON ObjectId:
import org.bson.types.ObjectId class Person {
ObjectId id }
BSON ObjectId instances are generated in a similar fashion to UUIDs.
So you should replace your domain class's id using org.bson.types.ObjectId
I figured out that I could create a new ObjectId first then when I insert it into the mongoDb, I pass the ObjectId.str for the "_id" property, then problem resolved, both mongo db level and grails level will have String type for id field.
Code snippet is as following for mongo javascript script:
conn = new Mongo();
db = conn.getDB("dbName");
db.user.find().forEach( function(userDoc) {
// Create a new object Id
objectId = new ObjectId();
db.userRole.insert({
_id: objectId.str, // Before we insert, convert it as a String
role: "51437d742cd1d9e80a3f0644",
user: userDoc._id
});
});