我有一个MongoDB集合,其中包含如下示例文档:
我想要做的是(从实际代码中可以看到)更新role
中的members.x.role
字段,其中members.x.id
等于给定ID(ID为UUID,因此它&# 39; s唯一;这部分代码没有问题)然后我想返回members.x
。但问题是它总是返回第一个成员而不是刚刚更新的成员。我已经尝试了一些 mgo 的方法,发现Distinct()
最接近我的期望,但这并不是我想要的。
我的问题是如何以指定的ID返回member
嵌入式文档 ?
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
}
答案 0 :(得分:0)
我找到了一个解决方法,它不是严格的Mongo查询返回这个嵌入式文档,但是这个代码比一些花哨的Mongo查询更加清晰和可理解,无论如何都会获取整个文档。
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")
}