Bruno Canongia
Bruno Canongia

Reputation: 524

How to get ObjectID as String from mongo-go-driver cursor?

I would like to get ObjectID as a string because I have other storage types, so I want to avoid to use primitive.ObjectID in my struct to keep the layers independent. I'm new to Golang, thanks.

package listing

type Card struct {
    ID       string
    Hanzi    string
    Pinyin   string
    Traducao string
}

My storage file: package storage

func (m *Mongodb)GetCards() []*listing.Card {
    var list []*listing.Card

    collection := m.Client.Database("flashcards").Collection("cards")
    cur, err := collection.Find(context.TODO(), bson.M{})

    if err != nil {
        log.Fatal("Erro buscando cards:", err)
    }
    for cur.Next(context.TODO()) {
        var card listing.Card
        err = cur.Decode(&card)
        if err != nil {
            log.Fatal("Erro decodificando documento", err)
        }
        list = append(list, &card)
    }
    return list
}

Upvotes: 6

Views: 7682

Answers (4)

Cirelli94
Cirelli94

Reputation: 1867

Like you, I was looking for a solution to keep modules as independent as possible and keep coupling levels low. I scratched my head A LOT but in the end, I found this. I hope it's a valid and clear, solution.

You can use a custom type that implements the ValueMarshaler interface: so you have to implement MarshalValue func!

type Card struct {
    ID       MyObjectID `bson:"_id"`
    CardSuit string     `bson:"cardSuit"`
}

type MyObjectID string

func (id MyObjectID) MarshalBSONValue() (bsontype.Type, []byte, error) {
    p, err := primitive.ObjectIDFromHex(string(id))
    if err != nil {
        return bsontype.Null, nil, err
    }

    return bson.MarshalValue(p)
}

ID is practically a string, but with the custom marshaller, it will be saved as an ObjectID in Mongo, and parsed correctly during unmarshalling.

Here is a working example, obviously, you need mongo to make it run.

Related question that helped me.

Upvotes: 6

zim
zim

Reputation: 19

For me it works out of the box when having the bson annotation (version 5.0.6):

type User struct {
    Id   string `bson:"_id,omitempty" json:"id,omitempty"`
    Name string `bson:"name" json:"name"`
}

Upvotes: 0

Eklavya
Eklavya

Reputation: 18430

Use bson:"-" for ignore ObjectID in response and json:"-" for ignoring in database. And you don't need to decode two times.

type Card struct {
    ObjectID primitive.ObjectID `json:"-" bson:"_id"`
    ID       string             `bson:"-"`
    Hanzi    string
    Pinyin   string
    Traducao string
}

err = cur.Decode(&card)
card.ID = card.ObjectID.Hex()

Upvotes: -2

Bruno Canongia
Bruno Canongia

Reputation: 524

Ok, I figured out. I created another struct just to hold the ObjectId

type HexId struct {
    ID primitive.ObjectID `bson:"_id"`
}

then I used Hex() to pass the value to Card.ID

err = cur.Decode(&card)
err = cur.Decode(&hexId)
card.ID = hexId.ID.Hex()

Now I can use it to make links.

Upvotes: 1

Related Questions