有没有更好的方法在 mongo 上创建动态匹配?
Is there a better way to create a dynamic match on mongo?
我正在创建一个显示所有类型数据的视图。目前我正在使用大量的 if 语句来实现并为所有不同类型的请求创建一个匹配参数。我真的不认为写出 120 个可能的 if 语句是最好的方法……而且它越来越难以阻止。我希望有人能指出正确的方向。这是我目前所拥有的。
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
}
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 语句来实现并为所有不同类型的请求创建一个匹配参数。我真的不认为写出 120 个可能的 if 语句是最好的方法……而且它越来越难以阻止。我希望有人能指出正确的方向。这是我目前所拥有的。
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
}
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