0

I want to use DBref with go-mongo-driver but I couldn't find any example about it. How can I achieve this? I worked with Spring Data Mongodb before and you can indicate Dbref inside a class like :

@DBRef private EmailAddress emailAddress;

Is there anybody to show up a good example? Thanks in advance

akinKaplanoglu
  • 728
  • 2
  • 8
  • 26

1 Answers1

7

I worked with Spring Data Mongodb before and you can indicate Dbref inside a class

Unless you have a compelling reason to use DBRefs you should avoid it, or use manual references instead.

With the example that you posted, you should definitely try to embed the value of EmailAddress in the document first. Using an embedded model should save you from querying the database twice just to retrieve EmailAddress value. See also Embedded Data Models.

type User struct 
{
    ID           primitive.ObjectID `json:"ID" bson:"_id"`
    UserName     string             `json:"username"`
    EmailAddress Email              `json:"emailAddress"`
}

type Email struct 
{
     PrivateEmail     string      `json:"private"`
     BusinessEmail    string      `json:"business"`
}

In some cases, where you do need to store related information in separate documents, you should use manual references. You can do this by saving the _id field of one document in another document as a reference. Then your application can run a second query to return the related data. Since MongoDB v3.4+, you can use either $lookup or $graphLookup to perform a lookup.

MongoDB Go driver does not have direct support for DBRef type. Spring Data MongoDB provides a convenient helper methods that form the query of DBRef automatically, although behind the scene it's just querying the database twice.

Having said all the above, and there's some special edge case that you need it you can construct your own struct as below example:

type User struct 
{
    ID               primitive.ObjectID  `json:"ID" bson:"_id"`
    UserName         string              `json:"username"`
    EmailAddress     DBRef               `json:"emailAddress"`
}

type DBRef struct {
   Ref interface{}   `bson:"$ref"`
   ID  interface{}   `bson:"$id"`
   DB  interface{}   `bson:"$db"`
}

Again, please note that MongoDB drivers do not automatically resolve DBRef. There may be frameworks or helpers on top of the driver that could provide the automatic reference resolution (looking up the value by performing a second query).

Wan B.
  • 18,367
  • 4
  • 54
  • 71
  • 1
    What if my Email object changes frequently? I think your first advice is not suitable for me. Manual reference seems the best option. What do you think about that @Wan Bachtiar? – akinKaplanoglu Mar 04 '20 at 19:06
  • 1
    By `Email` object, do you mean the `Email` struct ? if that changes frequently, you can just not have an object mapping. That would be the same as resolving the DBRef without knowing the struct. – Wan B. Mar 04 '20 at 23:47
  • Yes I mean Email struct. A user's email can change frequently @Wan Bachtiar. – akinKaplanoglu Mar 05 '20 at 17:15
  • There's a different between changing the struct and the value of the property inside of the struct. Changing value is quite easily done via update operations. – Wan B. Mar 05 '20 at 22:43
  • Let's say there is a many to many relationship with user and email. In that example embedding email is not the best option. If an email changes(the property changes) it does not make sense updating the embedded email object in whole users collection. What do you think @Wan Bachtiar ? – akinKaplanoglu Mar 06 '20 at 06:06
  • 1
    I think you mean one-to-many, many-to-many doesn't make sense or not common for user/email relationship. Really depends on your use case. You can either have one-to-many and store emails on a different collection and use `$lookup` to join user and email, or you can have one-to-few and have an array of emails embedded on user collection. – Wan B. Mar 07 '20 at 05:11