【问题标题】:Golang MongoDB not returning on conditional queryGolang MongoDB 没有返回条件查询
【发布时间】:2019-06-24 10:04:13
【问题描述】:

我有这个使用官方 mongo-go-driver (https://github.com/mongodb/mongo-go-driver) 的函数

func FindItemMongo(dataStruct interface{}, subItemKey string, collectionName string)(){
    fmt.Println("inside FindDataMongo in Controller")
    localDB := DB
    coll := localDB.Collection(collectionName)
    ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
    var searchData []uint8
    if subItemKey==""{
        fmt.Println("inside no key searchData")
        searchData, _ = bson.Marshal(bson.M{"data": dataStruct})
        fmt.Println("value of searchData")
        fmt.Println(searchData)
        fmt.Println("value of reflect type of searchData")
        fmt.Println(reflect.TypeOf(searchData))
    }else{
        reflectItem := reflect.ValueOf(dataStruct)
        subItem := reflectItem.FieldByName(subItemKey)
        subItemString := subItem.Interface().(string)
        searchData, _ =  bson.Marshal(bson.M{"data": bson.M{strings.ToLower(subItemKey): bson.M{"$eq": subItemString}}})
        fmt.Println("value of searchData")
        fmt.Println(searchData)
        fmt.Println("value of reflect type of searchData")
        fmt.Println(reflect.TypeOf(searchData))
    }
    cursor, err := coll.Find(ctx, searchData)
    if err != nil {
        log.Fatal(err)
    }
    defer cursor.Close(ctx)
    var returnBson []map[string]interface{}
    var result bson.M
    for cursor.Next(ctx) {
        err := cursor.Decode(&result)
        if err != nil { log.Fatal(err) }
        fmt.Println("value of found parsed")
        fmt.Println(result)
        returnBson = append(returnBson, result)
    }
}

它试图在与 if 语句相关的两个条件下查找数据库中的数据。如果未定义 subItemKey,则搜索与传入结构的完全匹配,如果定义了键,则使用 $eq 运算符在数据中搜索仅特定字段的匹配。

这适用于 subItemKey 为空的情况。像这样:

database.FindItemMongo(dataStruct, "", "users")

api       | 1:36:55 app         | value of found parsed
api       | map[_id:ObjectID("8494398fsfd") data:map[email:qwer password:wer token:...]]

但是,如果我使用命令:

database.FindItemMongo(dataStruct, "Email", "users")

我什么也得不到。

我在 else 语句中定义 searchData 的方式不正确,我不确定是什么。有谁知道出了什么问题?

编辑

我应该提到

的结果
    unmarshalledSearch := bson.M{"data": bson.M{strings.ToLower(subItemKey): bson.M{"$eq": subItemString}}}
    fmt.Println("value of unmarshalledSearch")
    fmt.Println(unmarshalledSearch)

api       | value of unmarshalledSearch
api       | map[data:map[email:map[$eq:qwer]]]

这与从空字段查询返回的数据格式相同。这是问题的症结所在——如果 searchData 的格式似乎正确,为什么光标没有返回任何结果?

【问题讨论】:

  • 您的FindItemMongo 样本与上述相同。 dataStruct的内容是什么?
  • type Login struct{ Email string json:"email"` 密码字符串json:"password" 令牌字符串json:"token" } ` - 你是什么意思“...和上面一样”?
  • 我的意思是This works for the condition where the subItemKey is empty. Like this:However, if I use the command:的例子
  • 对不起!空的不应该有“电子邮件”子项。

标签: mongodb go mongodb-query


【解决方案1】:

我是 Golang 新手,没有测试环境,但我认为您应该从 MongoDB Documentation 中的示例开始并更改

var searchData []uint8
    searchData, _ =  bson.Marshal(bson.M{"data": bson.M{strings.ToLower(subItemKey): bson.M{"$eq": subItemString}}})

var searchData bson.D
    searchData = bson.D{{"data." + strings.ToLower(subItemKey), bson.D{{"$eq", subItemString}}}}

对于subItemKey 为空的情况,您绝对应该使用bison.D 而不是bison.M,因为如果字段顺序错误,您正在执行的整个子文档匹配将失败。

对于搜索完全匹配的特殊情况,可以使用简化格式

    searchData = bson.D{{"data." + strings.ToLower(subItemKey), subItemString}}

它可能无法解决您的问题,但至少遵循推荐的模式。

如果这不能解决您的搜索问题,请在您的帖子中添加您正在使用的 Mongo 驱动程序和数据库的版本、您希望检索的完整文档、dataStruct 类型的声明以及dataStruct 你正在传递。

【讨论】:

  • 谢谢 - 有很多人有类似的答案,但你是第一个。感谢您的帮助!
【解决方案2】:

给定结构Login

type Login struct {
    Email    string `json:"email"`
    Password string `json:"password"`
    Token    string `json:"token"`
}

假设你有数据

{data: {email: "name@example.com", password: "password", token: "token"}}

subItemKey 为空白时,您的搜索与上面完全相同。但是当您只使用电子邮件进行搜索时,语法应该是

{"data.email": "name@example.com"}

但您的代码生成的搜索条件为

{"data":{"email":{"$eq":"name@example.com"}}}

要使其工作,请从

更改行

searchData, _ = bson.Marshal(bson.M{"data": bson.M{strings.ToLower(subItemKey): bson.M{"$eq": subItemString}}})

searchData, _ = bson.Marshal(bson.M{"data." + strings.ToLower(subItemKey): subItemString})

【讨论】:

    【解决方案3】:

    我认为您想搜索嵌套属性,因此,您应该更改查询

    这个:

    searchData, _ =  bson.Marshal(bson.M{"data": bson.M{strings.ToLower(subItemKey): bson.M{"$eq": subItemString}}})
    

    nestedKey := fmt.Sprintf("data.%s", strings.ToLower(subItemKey))
    searchData, _ = bson.Marshal(bson.M{nestedKey: subItemString})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-25
      • 2013-05-15
      • 2017-04-04
      • 1970-01-01
      • 1970-01-01
      • 2022-01-03
      相关资源
      最近更新 更多