使用本机驱动程序附加到 mongo 查询

Appending to mongo query using native driver

我有以下代码:

type SearchReq struct {
    PageSize      int32
    Offset        int32
    Zipcode       string
    PracticeType  []string
    TreatmentType []string
    HasPhotos     bool
    LatLong       GeoLocationInput
}

func buildSearchQuery(searchOptions *database.SearchReq) bson.D {
var filter bson.D

if searchOptions.Zipcode != "" {
    filter = append(filter, bson.E{"zipcode", searchOptions.Zipcode})
}

if len(searchOptions.PracticeType) != 0 {
    filter = append(filter, bson.E{"practicetypes", bson.E{"$all", searchOptions.PracticeType}})
}

if len(searchOptions.TreatmentType) != 0 {
    filter = append(filter, bson.E{"treatments", bson.E{"$all", searchOptions.TreatmentType}})
}

if searchOptions.HasPhotos {
    filter = append(filter, bson.E{"avatarurl", bson.E{"$ne", nil}})
}

return filter
}

我正在尝试进行的查询之一如下所示:

db.providers.find({treatments: {$all: ["botox","not-botox"]}, zipcode: "90210"})

过滤器打印出这个:

1st run: [{zipcode 60010} {avatarurl {$ne <nil>}}]
2nd run: [{zipcode 90210} {treatments {$all [botox not-botox]}}]

该命令行查询会提取结果,而 Go 变体不会。我试过将其切换到地图但无济于事。我在这里做错了什么?

理想情况下,我正在尝试构建一种向一个查询添加一组条件的方法。

PS。来自命令行查询的记录

{ "_id" : ObjectId("6001d1aab756f9540e8850ba"), "name" : "Mr. Brandy Emmerich", "accountnumber" : "b0c6ee03ab", "displayname" : "Mr. Brandy Emmerich", "streetaddress" : "92813 Funk Isle", "city" : "New Artville", "statename" : "Oklahoma", "zipcode" : "90210", "websiteurl" : "http://wildermannikolaus.org/robert.wolf", "emailaddress" : "hosea.runte@example.com", "telephonenumber" : "", "hours" : [ { "day" : 0, "open" : ISODate("2021-01-15T17:32:26.383Z"), "close" : ISODate("2021-01-15T17:32:26.383Z") }, { "day" : 1, "open" : ISODate("2021-01-15T17:32:26.383Z"), "close" : ISODate("2021-01-15T17:32:26.383Z") }, { "day" : 2, "open" : ISODate("2021-01-15T17:32:26.383Z"), "close" : ISODate("2021-01-15T17:32:26.383Z") }, { "day" : 3, "open" : ISODate("2021-01-15T17:32:26.383Z"), "close" : ISODate("2021-01-15T17:32:26.383Z") }, { "day" : 4, "open" : ISODate("2021-01-15T17:32:26.383Z"), "close" : ISODate("2021-01-15T17:32:26.383Z") }, { "day" : 5, "open" : ISODate("2021-01-15T17:32:26.383Z"), "close" : ISODate("2021-01-15T17:32:26.383Z") }, { "day" : 6, "open" : ISODate("2021-01-15T17:32:26.383Z"), "close" : ISODate("2021-01-15T17:32:26.383Z") } ], "instagramurl" : "https://instagram.com/ilene.kunde", "twitterurl" : "https://twitter.com/ilene.kunde", "facebookurl" : "https://facebook.com/ilene.kunde", "avatarurl" : "http://wehner.name/nick", "treatments" : [ "botox", "not-botox" ], "practicetypes" : null, "tags" : [ "", "", "", "id", "delectus", "pariatur" ], "metadata" : { "dolorem" : "excepturi", "numquam" : "at" }, "created_at" : ISODate("2021-01-15T17:32:26.383Z") }
{ "_id" : ObjectId("6001d1d0701489602c55f82a"), "name" : "Clara McLaughlin", "accountnumber" : "964a3de178", "displayname" : "Clara McLaughlin", "streetaddress" : "8708 Rodolfo Prairie", "city" : "Parisianburgh", "statename" : "West Virginia", "zipcode" : "90210", "websiteurl" : "http://pollich.org/kimberly_rau", "emailaddress" : "emiliano@example.org", "telephonenumber" : "", "hours" : [ { "day" : 0, "open" : ISODate("2021-01-15T17:33:04.526Z"), "close" : ISODate("2021-01-15T17:33:04.526Z") }, { "day" : 1, "open" : ISODate("2021-01-15T17:33:04.526Z"), "close" : ISODate("2021-01-15T17:33:04.526Z") }, { "day" : 2, "open" : ISODate("2021-01-15T17:33:04.526Z"), "close" : ISODate("2021-01-15T17:33:04.526Z") }, { "day" : 3, "open" : ISODate("2021-01-15T17:33:04.526Z"), "close" : ISODate("2021-01-15T17:33:04.526Z") }, { "day" : 4, "open" : ISODate("2021-01-15T17:33:04.526Z"), "close" : ISODate("2021-01-15T17:33:04.526Z") }, { "day" : 5, "open" : ISODate("2021-01-15T17:33:04.526Z"), "close" : ISODate("2021-01-15T17:33:04.526Z") }, { "day" : 6, "open" : ISODate("2021-01-15T17:33:04.526Z"), "close" : ISODate("2021-01-15T17:33:04.526Z") } ], "instagramurl" : "https://instagram.com/presley", "twitterurl" : "https://twitter.com/presley", "facebookurl" : "https://facebook.com/presley", "avatarurl" : "http://baumbach.com/minerva", "treatments" : [ "botox", "not-botox" ], "practicetypes" : null, "tags" : [ "", "", "", "corporis", "eveniet", "velit" ], "metadata" : { "enim" : "nisi" }, "created_at" : ISODate("2021-01-15T17:33:04.526Z") }

问题在于您如何添加复合过滤器。如果它们不是单个值,例如您正在使用 $all$ne,您必须使用“完整”文档作为它们的值。 bson.E 不是“完整”文档,它只是文档的一个 元素 。完整文档为 bson.Dbson.M.

所以使用它作为您的过滤器构建器:

func buildSearchQuery(searchOptions *database.SearchReq) bson.D {
    var filter bson.D

    if searchOptions.Zipcode != "" {
        filter = append(filter, bson.E{"zipcode", searchOptions.Zipcode})
    }

    if len(searchOptions.PracticeType) != 0 {
        filter = append(filter, bson.E{"practicetypes", bson.D{{"$all", searchOptions.PracticeType}}})
    }

    if len(searchOptions.TreatmentType) != 0 {
        filter = append(filter, bson.E{"treatments", bson.D{{"$all", searchOptions.TreatmentType}}})
    }

    if searchOptions.HasPhotos {
        filter = append(filter, bson.E{"avatarurl", bson.D{{"$ne", nil}}})
    }

    return filter
}

另请注意,如果 searchOptions 为空,则上述内容将 return nil,这作为过滤器是无效的。确保将其初始化为非 nil 空切片。所以而不是

var filter bson.D

使用

filter := bson.D{}

另请注意,使用 bson.M 而不是 bson.D 更简单:

func buildSearchQueryMap(searchOptions *database.SearchReq) bson.M {
    filter := bson.M{}

    if searchOptions.Zipcode != "" {
        filter["zipcode"] = searchOptions.Zipcode
    }

    if len(searchOptions.PracticeType) != 0 {
        filter["practicetypes"] = bson.M{"$all": searchOptions.PracticeType}
    }

    if len(searchOptions.TreatmentType) != 0 {
        filter["treatments"] = bson.M{"$all": searchOptions.TreatmentType}
    }

    if searchOptions.HasPhotos {
        filter["avatarurl"] = bson.M{"$ne": nil}
    }

    return filter
}