col.Find with regexp /foo/ fails
hokapoka opened this issue · comments
I'd like to query using mongo's regexp search, for example :
db.mycollection.find( { name:/foo/ } )
Where it will match any documents whose "name" property contains "foo"
I have tried to use:
q := map[string]string{ "name":"/foo/", }
But it will only match on name that exatcly match the string "/foo/",
as you would expect.
So I tried to use go lang's regexp package for example :
===================================
package main import ( mongo "github.com/mikejs/gomongo/mongo" "regexp" ) func main(){ conn, _ := mongo.Connect("127.0.0.1") db := conn.GetDB("test") col := db.GetCollection("mycollection") q, _ := mongo.Marshal(map[string]interface{}{ "name":regexp.MustCompile("/foo/"), }) col.FindOne(q) }
But it panics at runtime, I've attached the output at the bottom.
I wasn't sure if I should be using the regexp Package or some other
type to pass. I've looked through the tests and can't see regexp
used.
Have you got any suggestions.
panic: runtime error: invalid memory address or nil pointer dereference panic PC=0x7f5624538d50 runtime.panic+0xa7 /home/andrew/go/src/pkg/runtime/proc.c:1065 runtime.panic(0x49408c, 0x7f562457c680) runtime.panicstring+0x69 /home/andrew/go/src/pkg/runtime/runtime.c:83 runtime.panicstring(0x5c0a5f, 0x2200000004) runtime.sigpanic+0x144 /home/andrew/go/src/pkg/runtime/linux/thread.c:286 runtime.sigpanic() github%2ecom/mikejs/gomongo/mongo.*opQuery·Bytes+0x1d9 /home/andrew/go/src/pkg/github.com/mikejs/gomongo/mongo/message.go:179 github%2ecom/mikejs/gomongo/mongo.*opQuery·Bytes(0x7f5624556870, 0x200000008, 0x7f5624538f18, 0x7f5624538f08) github%2ecom/mikejs/gomongo/mongo.*Connection·sendMessageToReply+0x38 /home/andrew/go/src/pkg/github.com/mikejs/gomongo/mongo/collection.go:49 github%2ecom/mikejs/gomongo/mongo.*Connection·sendMessageToReply(0x7f562457c580, 0x7f56245568a0, 0x7f5624556870, 0x7f560383065c, 0x7f5624556870 github%2ecom/mikejs/gomongo/mongo.*Collection·Query+0x104 /home/andrew/go/src/pkg/github.com/mikejs/gomongo/mongo/collection.go:104 github%2ecom/mikejs/gomongo/mongo.*Collection·Query(0x7f5624558540, 0x0, 0x0, 0x100000000, 0x7f5624538ff0, ...) github%2ecom/mikejs/gomongo/mongo.*Collection·FindOne+0x50 /home/andrew/go/src/pkg/github.com/mikejs/gomongo/mongo/collection.go:124 github%2ecom/mikejs/gomongo/mongo.*Collection·FindOne(0x7f5624558540, 0x0, 0x0, 0x0, 0x7f5624556420, ...) main.main+0x166 /home/andrew/testgomonog/main.go:59 main.main() runtime.mainstart+0xf /home/andrew/go/src/pkg/runtime/amd64/asm.s:77 runtime.mainstart() runtime.goexit /home/andrew/go/src/pkg/runtime/proc.c:148 runtime.goexit() goroutine 2 [3]: runtime.entersyscall+0x28 /home/andrew/go/src/pkg/runtime/proc.c:572 runtime.entersyscall() syscall.Syscall6+0x5 /home/andrew/go/src/pkg/syscall/asm_linux_amd64.s:40 syscall.Syscall6() syscall.EpollWait+0x8d /home/andrew/go/src/pkg/syscall/zsyscall_linux_amd64.go:188 syscall.EpollWait(0x7f5600000006, 0x7f562457c4b0, 0x100000001, 0xffffffff, 0xc, ...) net.*pollster·WaitFD+0xfe /home/andrew/go/src/pkg/net/fd_linux.go:116 net.*pollster·WaitFD(0x7f562457c3a0, 0x0, 0x0, 0x0, 0x0, ...) net.*pollServer·Run+0xa3 /home/andrew/go/src/pkg/net/fd.go:207 net.*pollServer·Run(0x7f562454c780, 0x0) runtime.goexit /home/andrew/go/src/pkg/runtime/proc.c:148 runtime.goexit()
I'#ve found a solution that gets me going, although I'm not sure is the best solution as mongo must be having to eval(uate) at runtime :
q, _ := mongo.Marshal(map[string]interface{}{ "$where":"/foo/.test(this.name)", })
Anyone else got a better solution?
Hi hokapoka
In gomongo there is a code responsible for processing regexp. But probably the author has forgotten to add support in Marshal () sub. This small patch partially solves a problem, but I ask to notice - without support of "options".
diff --git a/mongo/bson-struct.go b/mongo/bson-struct.go index b01cb2b..a7dd70b 100644 --- a/mongo/bson-struct.go +++ b/mongo/bson-struct.go @@ -16,6 +16,7 @@ import ( "time" "container/vector" "strconv" + "regexp" ) type structBuilder struct { @@ -289,6 +290,8 @@ func Marshal(val interface{}) (BSON, os.Error) { return &_Long{int64(v), _Null{}}, nil case *time.Time: return &_Date{v, _Null{}}, nil + case *regexp.Regexp: + return &_Regex{v.String(), "", _Null{}}, nil } var value reflect.Value
Work example
dmitrys@laptop:~/tmp$ mongo MongoDB shell version: 1.6.6-pre- connecting to: test > db.products.find() { "_id" : ObjectId("4d4805cf59235ebab2f68173"), "name" : "HTC A8181 Desire", "price" : 578 } { "_id" : ObjectId("4d4805df59235ebab2f68174"), "name" : "HTC A3333 Wildfire", "price" : 341 } { "_id" : ObjectId("4d48060859235ebab2f68175"), "name" : "HTC A6363 Legend", "price" : 579 } { "_id" : ObjectId("4d48062959235ebab2f68176"), "name" : "HTC T3333 Touch2", "price" : 285 } { "_id" : ObjectId("4d4806a859235ebab2f68177"), "name" : "HTC B3333 NotExisting", "price" : 1 } > exit bye dmitrys@laptop:~/tmp$ dmitrys@laptop:~/tmp$ cat main.go package main import ( "os" "fmt" "regexp" "github.com/mikejs/gomongo/mongo" ) func main() { var dbc *mongo.Connection var err os.Error var query mongo.BSON var cursor *mongo.Cursor mmap := make(map[string]interface{}) mmap["name"] = regexp.MustCompile("(T|A)3333") query ,err = mongo.Marshal(mmap) if err != nil { fmt.Println(err) return } if dbc, err = mongo.Connect("localhost"); err != nil { fmt.Println(err) return } collection := dbc.GetDB("test").GetCollection("products") if cursor, err = collection.Query(query,0,0); err != nil { fmt.Println(err) return } for { if !cursor.HasMore() { break } data, _ := cursor.GetNext() //fmt.Printf("Dump: %#v\n",data) fmt.Printf("Name: %s\n",data.Get("name").String()) fmt.Printf("Price: %f\n\n",data.Get("price").Number()) } } dmitrys@laptop:~/tmp$ dmitrys@laptop:~/tmp$ 8g main.go && 8l main.8 && ./8.out Name: HTC A3333 Wildfire Price: 341.000000 Name: HTC T3333 Touch2 Price: 285.000000 dmitrys@laptop:~/tmp$
Hey deletus
That's great, at least in cases where there's no need to use options I can use the golang regexp.
I know there still some work to be done on the golang regexp package, maybe it'll be easier to add options when this happens.
Many thanks.
dagmark
That's the reason I open this issue, if you read the first message you'll see it panics if you use regexp.
I hadn't seen that implementation of a the go-mongo drive before. Thanks for links to it I'll install it later today and if I can use it as a drop-in replacement for this driver.
Thanks.
dagmark - I always hit the wrong button.