在golang中使用$or和$and组合的MongoDB查找查询

huangapple go评论144阅读模式
英文:

MongoDB find query with combination of $or and $and in golang

问题

我想获取满足以下条件的行:

{修理字段包含“ac”或{修理为“tv”且电话字段在1091-1100范围内}}

我正在尝试以下查询:

type M map[string]interface{}
conditions := M{"name": M{"$regex": "me"},
	"$or": []M{M{"repair": M{"$eq": "ac"}},
"$and": []M{M{"repair": M{"$eq": "tv"}}, M{"phone": M{"$gte": 1091, "$lte": 1100}}}}}
	fmt.Println(conditions)
	err = c.Find(conditions).Sort("phone").Limit(20).All(&j)

然而,我得到了一个编译错误:

索引必须是非负整数常量
无法将[]M字面量(类型[]M)用作数组或切片字面量中的M类型。
英文:

I want to get rows where:

{repair field has "ac" OR {repair is "tv" and phone field in range 1091-1100}}

I am trying the following query:

type M map[string]interface{}
conditions := M{"name": M{"$regex": "me"},
	"$or": []M{M{"repair": M{"$eq": "ac"}},
"$and": []M{M{"repair": M{"$eq": "tv"}}, M{"phone": M{"$gte": 1091, "$lte": 1100}}}}}
	fmt.Println(conditions)
	err = c.Find(conditions).Sort("phone").Limit(20).All(&j)

However, I am getting a compile error:

index must be non-negative integer constant
cannot use []M literal (type []M) as type M in array or slice literal.

答案1

得分: 1

你在"$and"之前缺少一个M{,在添加这个之后,不要忘记再添加一个闭合大括号}

这是好的代码这是有问题的代码,供你对比。

英文:

You're missing one M{ before "$and" and after you add that don't forget to add another closing brace }.

the good and the bad for comparison.

答案2

得分: 0

我不知道你在使用哪个驱动程序,但我可能会这样做:

package main

import (
	"log"
	"time"

	mgo "gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

const (
	databaseString = ""
)

var db DataStore

type DataStore struct {
	Session *mgo.Session
}

// 连接数据库
func (ds *DataStore) ConnectToDB() {

	mongoDBDialInfo := &mgo.DialInfo{
		Addrs:   []string{"localhost:27017"},
		Timeout: 1 * time.Hour,
	}

	sess, err := mgo.DialWithInfo(mongoDBDialInfo)
	if err != nil {
		sess.Refresh()
		panic(err)
	}
	sess.SetMode(mgo.Monotonic, true)
	db.Session = sess
}

// J 是预期的 MongoDB 返回对象
type J struct {
	ID     bson.ObjectId `bson:"_id,omitempty" json:"_id"`
	Status string        `bson:"status" json:"status"`
}

func init() {
	db.ConnectToDB()
}

func main() {
	colectionString := ""
	var j J

	conditions := bson.M{
		"name": bson.M{"$regex": "me"},
		"$or": []bson.M{
			bson.M{"repair": bson.M{"$eq": "ac"}},
		},
		"$and": []bson.M{
			bson.M{"repair": bson.M{"$eq": "tv"}},
			bson.M{"phone": bson.M{"$gte": 1091, "$lte": 1100}},
		},
	}

	err := db.Session.DB(databaseString).C(colectionString).Find(conditions).Sort("phone").Limit(20).All(&j)
	if err != nil {
		log.Fatal(err)
	}
}

我可能还会创建一个单独的包来处理 MongoDB 连接,这样我可以在调用周围编写包装函数:

func FindItem(sess *mgo.Session, id string) (data, error) {
	defer sess.Close()
	var res data // 一些数据类型的结构体
	err := sess.DB("my db").C("my collection").Find(bson.M{"user": someID}).One(&data)
	return data, err
}

然后我可以这样做,以支持并发:

res, err := packagemain.FindItem(sess.Copy(), someID)

在你的原始代码中,你缺少了 },。我建议你使用 go vet 或一个可以为你检查代码的 IDE。另外,如果你还没有使用 mgo,那么你可能需要使用它作为 MongoDB 驱动程序。

英文:

I don't know what driver your using, but I would probably do something like this..

package main
import (
"log"
"time"
mgo "gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
const (
databaseString = ""
)
var db DataStore
type DataStore struct {
Session *mgo.Session
}
// database
func (ds *DataStore) ConnectToDB() {
mongoDBDialInfo := &mgo.DialInfo{
Addrs:   []string{"localhost:27017"},
Timeout: 1 * time.Hour,
}
sess, err := mgo.DialWithInfo(mongoDBDialInfo)
if err != nil {
sess.Refresh()
panic(err)
}
sess.SetMode(mgo.Monotonic, true)
db.Session = sess
}
// J is the expected mongo return object
type J struct {
ID bson.ObjectId `bson:"_id,omitempty" json:"_id"`
// example data below
Status string `bson:"status" json:"status"`
}
func init() {
db.ConnectToDB()
}
func main() {
colectionString := ""
// probably best if this was a mapped mgo struct see above
// var j bson.M
var j J
// your orignal code
// I don't know why you are using $eq couldn't you just do bson.M{"repair":"ac"}, and bson.M{"repair":"tv"}
conditions := bson.M{"name": bson.M{"$regex": "me"},
"$or": []bson.M{
bson.M{"repair": bson.M{"$eq": "ac"}},
},
"$and": []bson.M{
bson.M{"repair": bson.M{"$eq": "tv"}},
bson.M{"phone": bson.M{"$gte": 1091, "$lte": 1100}},
}}
err := db.Session.DB(databaseString).C(colectionString).Find(conditions).Sort("phone").Limit(20).All(&j)
if err != nil {
log.Fatal(err)
}
}

I would probably also end up creating a separate package for the mongo connection stuff so that I can write wrapper functions around calls,

func FindItem(db *mgo.Session, id string) (data, error) {
defer sess.Close()
var res data //some data type struct
err := sess.DB("my db").C("my collection").Find(bson.M{"user": someID}).One(&data)
return data, err
}

then I'd be able to do things like this, which allow for concurrency

res, err := packagemain.FindItem(sess.Copy(), someID)

and your original code your you where missing } and ,. I suggest you use go vet or an ide which vets the code for you. Also, mgo is the mongo driver you probably what you want to be using if you're not using it already.

huangapple
  • 本文由 发表于 2017年9月13日 18:01:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/46194546.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定