1

Getting a string as input (from a user search), I am trying to construct a bson.M object for mgo to search through the mongo database and find x number of items.

Something like this

func Search (w http.ResponseWriter, r *http.Request) {

    q := r.FormValue("q")
    filter := bson.M{}
    // magic happens here 

    // do db connection stuff
    things := []*thing{}
    err := db.Find(&filter).Limit(10).All(&things)
    // check error, send things, etc
}

What I need the search to be based on is

  • ignore case (I found this answer which takes me part of the way)
  • the title in the stored data must, somewhere, include each of the words in the q.

So for instance if the stored data looks like {title: "abcde"}, then

  • Abc will match
  • de Bc will match
  • ac will not match

Edit: Solution

I finally figured it out. The magic part looks like this:

q := r.FormValue("q")
qs := strings.Split(q, " ")
and := make([]bson.M, len(qs))
for i, q := range qs {
    and[i] = bson.M{"title": bson.M{
        "$regex": bson.RegEx{Pattern: ".*" + q + ".*", Options: "i"},
    }}
}
filter := bson.M{"$and": and}

2 Answers 2

1

The mongo filter can take regex, for example;

        bson.M{"title": bson.M{"$regex": bson.RegEx{Pattern: title, Options: "i"}}}

So in this case the title variable would be something like; .*abc*.. The Options: "i" enables case insensitivity.

As for matching the substring (scenario 2) I am not sure how to achieve within regex.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks! – Pattern: title ? You mean Pattern: q right? And do you know how to do if q consists of more than one word?
Yes, but you need to add the relevant regex and I would suggest escaping/validating the input to ensure you are not exposed to a NoSql injection style attack.
Regarding the multiple words. I would imagine you can do some sort of string split and then use the $and keyword to chain the regex. (docs.mongodb.com/manual/reference/operator/query/and)
I feel I should be able to, but even that won't work for me. The googling continues..
I'll accept your answer since it was the answer that helped me the most, and so the question is considered to have a solution. :)
0

Simple use this,

wordOffset := q

selector:= bson.M{"title": bson.M{"$regex": wordOffset}}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.