有没有办法通过 Find() 获取切片?
Is there a way to get slice as result of Find()?
现在我在做:
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(或其他搜索函数)获取带用户名的切片,而无需结构和范围循环?
我看不出有什么比使用 append
的简单 range
循环更有效。如果没有所有 Mongo 的东西,你的代码基本上就是这样,而这正是我要做的。
package main
import (
"fmt"
)
type User struct {
Username string
}
func main() {
var users []User
users = append(users, User{"John"}, User{"Jane"}, User{"Jim"}, User{"Jean"})
fmt.Println(users)
// Interesting part starts here.
var myUsers []string
for _, user := range users {
myUsers = append(myUsers, user.Username)
}
// Interesting part ends here.
fmt.Println(myUsers)
}
MongoDB find()
的结果始终是文档列表。所以如果你想要一个值列表,你必须像你一样手动转换它。
使用自定义类型(派生自 string
)
另请注意,如果您要创建自己的类型(派生自 string
),您可以覆盖其解组逻辑,并且 "extract" 只是文档中的 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
,您可以简单地将 Username
转换为 string
.
使用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)
现在我在做:
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(或其他搜索函数)获取带用户名的切片,而无需结构和范围循环?
我看不出有什么比使用 append
的简单 range
循环更有效。如果没有所有 Mongo 的东西,你的代码基本上就是这样,而这正是我要做的。
package main
import (
"fmt"
)
type User struct {
Username string
}
func main() {
var users []User
users = append(users, User{"John"}, User{"Jane"}, User{"Jim"}, User{"Jean"})
fmt.Println(users)
// Interesting part starts here.
var myUsers []string
for _, user := range users {
myUsers = append(myUsers, user.Username)
}
// Interesting part ends here.
fmt.Println(myUsers)
}
MongoDB find()
的结果始终是文档列表。所以如果你想要一个值列表,你必须像你一样手动转换它。
使用自定义类型(派生自 string
)
另请注意,如果您要创建自己的类型(派生自 string
),您可以覆盖其解组逻辑,并且 "extract" 只是文档中的 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
,您可以简单地将 Username
转换为 string
.
使用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)