现在我正在做:
sess := mongodb.DB("mybase").C("mycollection") var users []struct { Username string `bson:"username"` } err = sess.Find(nil).Select(bson.M{"username": 1, "_id": 0}).All(&users) if err != nil { fmt.Println(err) } var myUsers []string for _, user := range users{ myUsers = append(myUsers, user.Username) }
有没有更有效的方法直接从Find(或其他搜索功能)中获取带有用户名的slice,而没有struct和range循环?
MongoDB的结果find()始终是文档列表。因此,如果要获取值列表,则必须像以前一样手动将其转换。
find()
string
另外请注意,如果您要创建自己的类型(从派生string),则可以覆盖其取消编组逻辑,并username仅从文档中“提取” 。
username
它看起来像这样:
type Username string func (u *Username) SetBSON(raw bson.Raw) (err error) { doc := bson.M{} if err = raw.Unmarshal(&doc); err != nil { return } *u = Username(doc["username"].(string)) return }
然后将用户名查询成片:
c := mongodb.DB("mybase").C("mycollection") // Obtain collection var uns []Username err = c.Find(nil).Select(bson.M{"username": 1, "_id": 0}).All(&uns) if err != nil { fmt.Println(err) } fmt.Println(uns)
请注意,这[]Username与并不相同[]string,因此这可能对您还不够。如果您需要一个用户名作为值的string代替,而不是Username在处理结果时,只需将a转换为Username即可string。
[]Username
[]string
Username
Query.Iter()
避免切片复制的另一种方法是调用Query.Iter(),迭代结果并username手动提取和存储,类似于上述自定义编组逻辑的工作方式。
var uns []string it := c.Find(nil).Select(bson.M{"username": 1, "_id": 0}).Iter() defer it.Close() for doc := (bson.M{}); it.Next(&doc); { uns = append(uns, doc["username"].(string)) } if err := it.Err(); err != nil { fmt.Println(err) } fmt.Println(uns)