4

Here is a challenge to my fellows MongoDB and NodeJs Devs

I have a search form, in which a user can enter the following:

225/65R16 71T K715 Hankook

As for my mongodb, I have a collection with the following docs:

1- { _id: SomeId, Description: 225/65R16 71T K715, Brand: Hankook, Ref: 123455 }
2- { _id: SomeId, Description: 225/65R16 71T K715, Brand: Continental, Ref: 123456 }
3- { _id: SomeId, Description: 225/65R16 94T Energy, Brand: Hankook, Ref: 123457 }

How can I do that so that when searching any combination below I get results for the docs 1 and 3 above?

List of combinations:

Hankook
225/65R16
225/65R16 Hankook
225 Hankook
225 Han
3
  • Not possible for that list of combinations: 71T is in document #2. Also, there's no way that would match on document #3. However, if you're looking to do a search in the manor it appears you are, you should look into text search indexes. Here's a good article: code.tutsplus.com/tutorials/… Commented Nov 18, 2016 at 2:22
  • Edited the question as the last 2 items I had in the list was a bad example. I guess a better question is how to search for values that match either or in two fields (description and brand) Commented Nov 18, 2016 at 2:42
  • You can use the $or operator: docs.mongodb.com/v3.2/reference/operator/query/or Commented Nov 18, 2016 at 2:43

4 Answers 4

2

You can try by creating an Index:

db.yourollection.createIndex({"Description":1,"Brand":1})

And then by searching for the value, Example:

mongoosemodel.find({$text:{$search: 225/65R16 Hankook}},{Description:1,Brand:1})

And, if you get more results than expected, you can make a filter by using Javascript.

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

1 Comment

Probably the best answer. Regex will work as pointed out by the other answers, but it's not scalable as it doesn't utilize your indexes. So the larger your tire collection becomes, the slow these queries will become.
2

You can use regular expressions to match the beginning of the fields and then use OR operator.

Assuming the following documents.

{ "Description" : "225/65R16 71T K715", "Brand" : "Hankook", "Ref" : 123455 }
{ "Description" : "225/65R16 71T K715", "Brand" : "Continental", "Ref" : 123455 }
{ "Description" : "225/65R16 94T", "Brand" : "Hankook", "Ref" : 123455 }

The following queries return the expected results.

> db.test.find({$or: [{Description: {$regex: '^225/65R16'}, Brand: {$regex: '^Hankook'}}]})
{ "Description" : "225/65R16 71T K715", "Brand" : "Hankook", "Ref" : 123455 }
{"Description" : "225/65R16 94T", "Brand" : "Hankook", "Ref" : 123455 }

> db.test.find({$or: [{Description: {$regex: '^225'}, Brand: {$regex: '^Han'}}]})
{ "Description" : "225/65R16 71T K715", "Brand" : "Hankook", "Ref" : 123455 }
{ "Description" : "225/65R16 94T", "Brand" : "Hankook", "Ref" : 123455 }

For 225/65R16 though there's no way to avoid matching document number 2 beacuse the query does not contain enough disambiguation information.

Comments

1

Here is an example based on a node.js, javascript and mongoose

you can look for a "search word" or "search term" in multiple fields in a collection like so :

var searchTerm = 'Hankook'; // put your search term here

YourMongooseModel.find({ 
    $or: [
        // in this example we want to search at two fields 'Description' and 'Brand'
        // however you can put any fields as you desire
        {"Description": {$regex: searchTerm, $options: "i"}},
        {"Brand": {$regex: searchTerm, $options: "i"}}
    ]
}, function (err, docs) {
    if(docs) {
        // handle retreived docs here
    }
});

Hope this helps. Thanks

Comments

0

Use aggregation to concat search fields, then simply use a regex :

// Build a regex from your string,
// Example : containing exactly all word, no order
enter code here
var a = "225/65R16 71T K715 Hankook"
var ar = a.split(new RegExp("\\s")); // [ '225/65R16', '71T', 'K715', 'Hankook' ]
var estr = ""
ar.forEach(function(e){ estr += "(?=.*\b"+e+"\b)";});
var re = new RegExp("^.*"+estr+".*$"); // /^.*(?=.*\b225\/65R16\b)(?=.*\b71T\b)(?=.*\bK715\b)(?=.*\bHankook\b).*$/



enter code here
db.a.aggregate([
   {
       $project:{
          st: {$concat:["$Brand"," ", "$Description"]}, 
         _id:1,
         Description:1,
         Brand:1,
         Ref:1
       }
   },
   {
      $match:{
         st: /^(?=.*\b225\/65R16\b)(?=.*\b71T\b)(?=.*\bK715\b)(?=.*\bHankook\b).*$/
      }
   }
])

// output { "_id" : ObjectId("582f009da52585177f054ddc"), "Description" : "225/65R16 71T K715", "Brand" : "Hankook", "Ref" : "123455", "st" : "Hankook 225/65R16 71T K715" }

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.