Check object existence in mongo using gopkg.in/mgo.v2 - mongodb

I am looking for convinient way to check if object already exists in collection. For now the only way that i have found is
type result interface{}
var res result
err := col.Find(bson.M{"title": "title1"}).One(&res)
if err != nil {
if err.Error() == "not found" {
log.Println("No such document")
} else {
log.Println("err occured", err)
}
}
I dont want to create variable res, in case if object exists, it can be very heavy document with a lot of fields.
I wish there would be another way, some Check() function which will just return bool value..
Basically I only need to know that object already stored in collection, I dont need itself

count, err = collection.Find(bson.M{field: value}).Count()

you have to use $exists
Syntax: { field: { $exists: } }
For more details
http://docs.mongodb.org/manual/reference/operator/query/exists/

in the Official Mongo Driver you can get count of documents with specific key using CountDocuments function :
count, err := collection.CountDocuments(context.TODO(), bson.D{{"key", "value"}})

Related

Is there a way that can find one document and clone it with changing id/value in mongodb with Go

suppose I have code like this:
var result bson.M
err := coll.FindOne(context.TODO(), filter).Decode(&result)
if err != nil {
panic(err)
}
// somehow I can change the _id before I do insertOne
if _, err := coll.InsertOne(context.TODO(), result); err != nil {
panic(err)
}
is there a way I can insertOne without knowing the data struct? But I have to change the _id before I insert it.
The ID field in MongoDB is always _id, so you may simply do:
result["_id"] = ... // Assign new ID value
Also please note that bson.M is a map, and as such does not retain order. You may simply change only the ID and insert the clone, but field order may change. This usually isn't a problem.
If order is also important, use bson.D instead of bson.M which retains order, but finding the _id is a little more complex: you have to use a loop as bson.D is not a map but a slice.
This is how it could look like when using bson.D:
var result bson.D
// Query...
// Change ID:
for i := range result {
if result[i].Key == "_id" {
result[i].Value = ... // new id value
break
}
}
// Now you can insert result

How to check if a record exists with golang and the offical mongo driver

I'm using the official mongo driver in golang, and am trying to determine if a record exists. Unfortunately the documentation doesn't explain how to do this. I'm attempting to do it with FindOne, but it returns and error when no results are found, and I don't know how to distinguish that error from any other error (short of comparing strings which feels wrong. What's the right way to check if a document exists in mongo with the official golang driver?
Here's my code.
ctx := context.Background()
var result Page
err := c.FindOne(ctx, bson.D{{"url", url}}).Decode(&result)
fmt.Println("err: ", err)
// how do I distinguish which error type here?
if err != nil {
log.Fatal(err)
}
Here's the answer.
var coll *mongo.Collection
var id primitive.ObjectID
// find the document for which the _id field matches id
// specify the Sort option to sort the documents by age
// the first document in the sorted order will be returned
opts := options.FindOne().SetSort(bson.D{{"age", 1}})
var result bson.M
err := coll.FindOne(context.TODO(), bson.D{{"_id", id}}, opts).Decode(&result)
if err != nil {
// ErrNoDocuments means that the filter did not match any documents in the collection
if err == mongo.ErrNoDocuments {
return
}
log.Fatal(err)
}
fmt.Printf("found document %v", result)

converting MongoDB function foreach into mgo (Golang) function

This is function that tries to update the code matching by its value
the res collection as having the code of Marque it will be compared with doc.Marque if it is the case it will be replaced by the value of the marque.
This code is working perfectly in mongoDB CLI, but as i am working with GO.
I tried to convert it into mgo as you may see below but it is not working , i did not find the foreach function in mgo , is there something to be replaced with in this case ? thanks for the help
db.res.find().forEach(function(doc){
var v = db.brands.findOne({code: doc.Marque});
if(v){
db.res.update({"Marque": doc.Marque},
{$set: {"Marque":v.value}}, {multi: true});
}
});
Here is what i tried :
result:=Results{}
pipe:=res.find(bson.M{}).Iter()
for pipe.Next(&result) {
brands:=brands.findOne({code: doc.Marque});
if(v){
pipe.update({"Marque": doc.Marque},
{$set: {"Marque": v.value}}, {multi: true});
}
}
Visit the mgo Godoc may help you understand how it works.
Second, exported types/functions in Golang are begin with a capital letter. So res.find, brands.findOne, ... should be res.Find, brands.FineOne respectively, if such functions exist.
// let's say you have a type like this
type myResult struct {
ID bson.ObjectId `bson:"_id"`
Marque string `bson:"Marque"`
// other fields...
}
// and another type like this
type myCode struct {
Code string `bson:"code"`
// other fields...
}
res := db.C("res")
brands := db.C("brands")
result := myResult{}
// iterate all documents
iter := res.Find(nil).Iter()
for iter.Next(&result) {
var v myCode
err := brands.Find(bson.M{"code": result.Marque}).One(&v)
if err != nil {
// maybe not found or other reason,
// it is recommend to have additional check
continue
}
query := bson.M{"_id": result.ID}
update := bson.M{"Marque": v.value}
if err = res.Update(query, update); err != nil {
// handle error
}
}
if err := iter.Close(); err != nil {
fmt.Println(err)
}

How to return embedded document with ID of

I have a MongoDB collection with an example document like this:
What I want to do (as you can see from the actual code) is to update a role field in members.x.role where members.x.id equals given ID (ID is UUID so it's unique; this part of code works without problem) and then I want to return that members.x. But the problem is that it always returns first member instead of the one that has been just updated. I've tried some methods of mgo and found Distinct() be closest to my expectations, but that doesn't work as I want.
My question is how can I return member embedded document with specified ID?
I've already looked on this and this but it didn't help me.
func (r MongoRepository) UpdateMemberRole(id string, role int8) (*Member, error) {
memberQuery := &bson.M{"members": &bson.M{"$elemMatch": &bson.M{"id": id}}}
change := &bson.M{"members.$.role": role}
err := r.db.C("groups").Update(memberQuery, &bson.M{"$set": &change})
if err == mgo.ErrNotFound {
return nil, fmt.Errorf("member with ID '%s' does not exist", id)
}
// FIXME: Retrieve this member from query below. THIS ALWAYS RETURNS FIRST MEMBER!!!
var member []Member
r.db.C("groups").Find(&bson.M{"members.id": id}).Distinct("members.0", &member)
return &member[0], nil
}
I found a workaround, it's not stricte Mongo query that is returning this embedded document, but this code is IMO more clear and understandable than some fancy Mongo query that fetches whole document anyway.
func (r MongoRepository) UpdateMemberRole(id string, role int8) (*Member, error) {
change := mgo.Change{
Update: bson.M{"$set": bson.M{"members.$.role": role}},
ReturnNew: true,
}
var updatedGroup Group
_, err := r.db.C("groups").Find(bson.M{"members": bson.M{"$elemMatch": bson.M{"id": id}}}).Apply(change, &updatedGroup)
if err == mgo.ErrNotFound {
return nil, fmt.Errorf("member with ID '%s' does not exist", id)
} else if err != nil {
return nil, err
}
for _, member := range updatedGroup.Members {
if member.Id == id {
return &member, nil
}
}
return nil, fmt.Errorf("weird error, Id cannot be found")
}

Check object value exist in mongodb document in golang using mgo package [duplicate]

I am looking for convinient way to check if object already exists in collection. For now the only way that i have found is
type result interface{}
var res result
err := col.Find(bson.M{"title": "title1"}).One(&res)
if err != nil {
if err.Error() == "not found" {
log.Println("No such document")
} else {
log.Println("err occured", err)
}
}
I dont want to create variable res, in case if object exists, it can be very heavy document with a lot of fields.
I wish there would be another way, some Check() function which will just return bool value..
Basically I only need to know that object already stored in collection, I dont need itself
count, err = collection.Find(bson.M{field: value}).Count()
you have to use $exists
Syntax: { field: { $exists: } }
For more details
http://docs.mongodb.org/manual/reference/operator/query/exists/
in the Official Mongo Driver you can get count of documents with specific key using CountDocuments function :
count, err := collection.CountDocuments(context.TODO(), bson.D{{"key", "value"}})