Which is the best way to handle arrays of ObjectIDs?

197 views
Skip to first unread message

imgood

unread,
Sep 2, 2015, 4:00:31 AM9/2/15
to mgo-users
Sorry, but I have very noob questions.

Suppose there is a struct
type Post struct {
  ID           bson
.ObjectID

 
CommentsIds  []
bson.ObjectID `bson:"comments" json:"-"`
 
Comments     []*Comment      `bson:"-" json:"comments"`
}

1. 
When I fetch Post object from DB I also fetch Comments field by hand. 
As I understand MGO doesn't have auto population so I have to put in this struct two fields: array of ids and array on objects (for later convenience page.Comments).
Is it a good way to make this things? Which convention do you use? I really can't stand these ugly tags :(

2.
Okay, then I want to add one or two comments and then save post. I saved comments as a separated documents and then append their ids into CommentIds.
.Update(post, {_id: ...}) saves entire document. But how to force MGO to update post object with just $push method? Or I have to make this operation manually?

3.
About logging.
These (http://grokbase.com/t/gg/mgo-users/152571ky82/how-to-show-query-log#20150209zwzki7mxjfigdzuqp245wskkl4) comments says that I need to set logger to see queries made to db, but there is nothing in console.
What I do wrong?
Here is my code:
func initDBSession() {
session, err := mgo.Dial("mongodb://localhost:27017/mydb")
if err != nil {
panic(fmt.Sprintf("Failed connect to Mongo (%v)", err))
}

//mgo.SetDebug(true) // this causes A LOT of output, so it doesn't suit for me

logout := log.New(os.Stdout, "MGO: ", log.Lshortfile)
mgo.SetLogger(logout)

dbSession = session // global variable
}


I spoiled by NodeJS Mongoose library where all such things are automated :(

Thanks in avance!

Gustavo Niemeyer

unread,
Sep 3, 2015, 11:11:45 AM9/3/15
to mgo-...@googlegroups.com
Hi,

On Wed, Sep 2, 2015 at 5:00 AM, imgood <godknow...@gmail.com> wrote:
Sorry, but I have very noob questions.

Suppose there is a struct
type Post struct {
  ID           bson
.ObjectID

 
CommentsIds  []
bson.ObjectID `bson:"comments" json:"-"`
 
Comments     []*Comment      `bson:"-" json:"comments"`
}

1. 
When I fetch Post object from DB I also fetch Comments field by hand. 
As I understand MGO doesn't have auto population so I have to put in this struct two fields: array of ids and array on objects (for later convenience page.Comments).
Is it a good way to make this things? Which convention do you use? I really can't stand these ugly tags :(

The way you are doing it sounds fine. Another way is to use an internal structure which you use when moving data to/from the database, and have a separate public structure in your API. A third option is to use an internal structure when interacting with the database, and have that structure as a private field inside the public structure, and have accessor methods to obtain and modify information in the private structure and on cached fields (that means you don't need to load _all_ comments every time you read a post, for example).

The best option, as usual, depends much on context.

2.
Okay, then I want to add one or two comments and then save post. I saved comments as a separated documents and then append their ids into CommentIds.
.Update(post, {_id: ...}) saves entire document. But how to force MGO to update post object with just $push method? Or I have to make this operation manually?

If you want to save the whole object, you can provide it entirely. If you want to use a $push, you should prepare the operation. The driver will not do anything magic.

3.
About logging.
These (http://grokbase.com/t/gg/mgo-users/152571ky82/how-to-show-query-log#20150209zwzki7mxjfigdzuqp245wskkl4) comments says that I need to set logger to see queries made to db, but there is nothing in console.
What I do wrong?

If you want to see every single query, you enable debug. Yes, it's a lot of data, because it's debug data. It wouldn't be sane to log all queries if you're not debugging.

I spoiled by NodeJS Mongoose library where all such things are automated :(

I wrote an ORM before, and I understand it's great when it does exactly what you want. The problem comes when you need anything non-trivial, such as when you need to make decisions about what to do when things go wrong, or what's the right order to do things if you need to consider the error paths for the operations, or when you need to use a better way to update documents instead of the one the ORM is implementing for you, and so on.

The mgo driver takes a middle-path approach: it goes a long way to offer you a very convenient way to manipulate structured values, including custom marshalers and unmarshalers that you can explore at will, but it is not an ORM and it won't become one. The clarity of what the code is doing and the flexibility of working with the actual database is a much more important asset than the convenience of updating a field behind you, at least in my view.


Reply all
Reply to author
Forward
0 new messages