【问题标题】:Is there a better way to create a dynamic match on mongo?有没有更好的方法在 mongo 上创建动态匹配?
【发布时间】:2017-08-02 23:28:09
【问题描述】:

我正在创建一个显示所有类型数据的视图。目前我正在使用大量的 if 语句来为 true 并为所有不同类型的请求创建一个匹配参数。如果陈述是最好的方法,我真的不认为写出 120 是可能的……而且它越来越难以阻止。我希望有人能指出正确的方向。这是我目前所拥有的。

func GetAllHourly(dbsession *mgo.Session, year, month, day, site, size, network, region string, code int) (items []MassAggregation, err error) {
    defer dbsession.Close()
    var match bson.M
    if network == "openx3" {
        network = "openx"
    }

    group := bson.M{"$group": bson.M{"_id": bson.M{"aws_region": "$aws_region", "http_request_status": "$http_request_status", "hour": "$hour", "network": "$network", "site": "$site", "size": "$size", "zone": "$zone", "extra": "$extra"}, "total": bson.M{"$sum": "$count"}}}
    if site == "" && size == "" && network == "" && region == "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day}}
    } else if site != "" && size == "" && network == "" && region == "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site}}
    } else if site != "" && size != "" && network == "" && region == "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site, "size": size}}
    } else if site != "" && size != "" && network != "" && region == "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site, "size": size, "network": &bson.RegEx{Pattern: network, Options: "i"}}}
    } else if site != "" && size != "" && network != "" && region != "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site, "size": size, "network": &bson.RegEx{Pattern: network, Options: "i"}, "aws_region": region}}
    } else if site != "" && size != "" && network != "" && region != "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site, "size": size, "network": &bson.RegEx{Pattern: network, Options: "i"}, "aws_region": region, "http_request_status": code}}
    } else if site == "" && size != "" && network == "" && region == "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site, "size": size}}
    } else if site == "" && size != "" && network != "" && region == "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "size": size, "network": &bson.RegEx{Pattern: network, Options: "i"}}}
    } else if site == "" && size != "" && network != "" && region != "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site, "size": size, "network": &bson.RegEx{Pattern: network, Options: "i"}, "aws_region": region}}
    } else if site == "" && size == "" && network != "" && region == "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "network": &bson.RegEx{Pattern: network, Options: "i"}}}
    } else if site == "" && size == "" && network != "" && region != "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "network": &bson.RegEx{Pattern: network, Options: "i"}, "aws_region": region}}
    } else if site == "" && size == "" && network != "" && region != "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "network": &bson.RegEx{Pattern: network, Options: "i"}, "aws_region": region, "http_request_status": code}}
    } else if site == "" && size == "" && network == "" && region != "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "aws_region": region}}
    } else if site == "" && size == "" && network == "" && region != "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "aws_region": region, "http_request_status": code}}
    } else if site == "" && size == "" && network == "" && region == "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "http_request_status": code}}
    } else if site != "" && size == "" && network == "" && region == "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site, "http_request_status": code}}
    } else if site != "" && size == "" && network == "" && region != "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site, "aws_region": region}}
    } else if site != "" && size == "" && network != "" && region == "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site, "network": &bson.RegEx{Pattern: network, Options: "i"}}}
    } else if site == "" && size != "" && network == "" && region == "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "size": size, "http_request_status": code}}
    } else if site == "" && size != "" && network == "" && region != "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "size": size, "aws_region": region}}
    } else if site == "" && size != "" && network != "" && region == "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "size": size, "network": &bson.RegEx{Pattern: network, Options: "i"}}}
    } else if site == "" && size == "" && network != "" && region == "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "network": &bson.RegEx{Pattern: network, Options: "i"}, "http_request_status": code}}
    } else if site == "" && size == "" && network != "" && region != "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "network": &bson.RegEx{Pattern: network, Options: "i"}, "aws_region": region}}
    } else if site != "" && size != "" && network != "" && region == "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "network": &bson.RegEx{Pattern: network, Options: "i"}, "size": size, "http_request_status": code}}
    } else if site != "" && size != "" && network == "" && region == "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "site": site, "size": size, "http_request_status": code}}
    } else if site == "" && size != "" && network != "" && region == "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "network": &bson.RegEx{Pattern: network, Options: "i"}, "size": size, "http_request_status": code}}
    } else if site != "" && size == "" && network != "" && region != "" && code == -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "network": &bson.RegEx{Pattern: network, Options: "i"}, "aws_region": region, "site": site}}
    } else if site != "" && size == "" && network != "" && region != "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "network": &bson.RegEx{Pattern: network, Options: "i"}, "aws_region": region, "site": site, "http_request_status": code}}
    } else if site != "" && size == "" && network == "" && region != "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "aws_region": region, "site": site, "http_request_status": code}}
    } else if site == "" && size != "" && network != "" && region != "" && code != -1 {
        match = bson.M{"$match": bson.M{"year": year, "month": month, "day": day, "network": &bson.RegEx{Pattern: network, Options: "i"}, "aws_region": region, "size": size, "http_request_status": code}}
    }

    operations := []bson.M{match, group}
    err = dbsession.DB("logs").C("prod").Pipe(operations).All(&items)
    return
}

如您所见,它不守规矩……但我还没有找到替代方案。我希望我还没有找到答案。

更新:我已经稍微改变了我的方法。我仍然很好奇这是否是最好的方法。

func GetAllHourly(dbsession *mgo.Session, year, month, day, site, size, network, region string, code int) (items []MassAggregation, err error) {
    defer dbsession.Close()
    matches := []bson.M{bson.M{"$match": bson.M{"year": year, "month": month, "day": day}}}
    if network == "openx3" {
        network = "openx"
    }

    if site != "" {
        matches = append(matches, bson.M{"$match": bson.M{"site": site}})
    }
    if size != "" {
        matches = append(matches, bson.M{"$match": bson.M{"size": size}})
    }
    if region != "" {
        matches = append(matches, bson.M{"$match": bson.M{"aws_region": region}})
    }
    if code != -1 {
        matches = append(matches, bson.M{"$match": bson.M{"http_request_status": code}})
    }
    if network != "" {
        matches = append(matches, bson.M{"$match": bson.M{"network": &bson.RegEx{Pattern: network, Options: "i"}}})
    }
    group := bson.M{"$group": bson.M{"_id": bson.M{"aws_region": "$aws_region", "http_request_status": "$http_request_status", "hour": "$hour", "network": "$network", "site": "$site", "size": "$size", "zone": "$zone", "extra": "$extra"}, "total": bson.M{"$sum": "$count"}}}
    var operations []bson.M
    for _, match := range matches {
        operations = append(operations, match)
    }
    operations = append(operations, group)
    err = dbsession.DB("logs").C("prod").Pipe(operations).All(&items)
    return
}

【问题讨论】:

  • 我从没想过go 会是一种打字友好的编程语言。有人称它为if err!=nil 语言。

标签: mongodb go mgo


【解决方案1】:

bson.M{} 只是 map[string]interface{} 的命名类型,您可以在文档中看到:http://godoc.org/labix.org/v2/mgo/bson#M

那么,为什么不直接将它用作字典来构建自定义查询呢?您将拥有更少的代码:

query := bson.M{}

if site != "" {
       query["site"] = site
    }
    if size != "" {
       query["size"] = size
    }

}

// Then use query variable for querying mongodb

【讨论】:

  • 我知道,那么我的第二次尝试在逻辑方面是最佳的?切换到映射字符串不会更改逻辑或删除 if 语句。我想知道的是是否有更好的匹配方法。假设我有 20 个切换。我真的需要写 20 个 if 语句吗?
  • 不能回避业务逻辑,所以必须使用if/switch语句。但是您仍然可以编写更少的代码,以最大程度地减少您和您的同事未来在理解方面的痛苦。此外,您需要在 Validate() 方法中的 SearchModel 结构中包含类似的代码,以验证从用户接收到的数据。下一级优化代码可读性、维护和安全性,而不是将搜索参数作为函数参数传递,使用此字段创建结构,然后将其传递给函数: func GetAllHourly(dbsession *mgo.Session, SearchModel search) (items []MassAggregation,错误错误){
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-29
  • 1970-01-01
  • 1970-01-01
  • 2013-12-08
  • 2019-12-09
相关资源
最近更新 更多