简体   繁体   中英

Custom search using Mongodb

I have a MongoDB as my database and the backend is written in node.js. I am trying to implement a search for a table which returns me all results with the string entered AND string matching.

For example searching "foo" will return (In that order)

  • foo maker moo

  • doo foo doo //The order of word search does not matter as long as it puts the word search first

  • foobar

  • fooboo

Currently I have this but I am convinced there is a better way to do it without searching the db twice:


    async function(req, res) {
        var customerName = req.params.customerName;
   //word match
        var customers1 = await Models.DummyContactTable.find({
            customerName: {
                $regex: "^" + customerName,
                $options: 'i'
            },
            IsActive: true
        });
    //String match
   
     var customers2 = await Models.DummyContactTable.find({
          $and: [
              {
                customerName: {
                  $regex: customerName, $options: 'i'
                }
              },
              {
                customerName: {
                  $not: {
                    $regex: "^" + customerName,
                  }
                },
                IsActive: true
              }
          ]
        });
    //Since sometimes we get duplicates, doing a filter and find to de-dup
      var customers = customers1.concat(customers2.filter((customer) => !customers1.find(f => f.uuid === customer.uuid)));

If you were using Atlas Search, you could write a query like this:

{ 
  $search: {
    autocomplete: { 
      path: "customerName",
      query: "foo"
}}}

// atlas search index definition
{
  "mappings": {
    "fields": {
      "customerName" : { 
        "type" : "autocomplete"
}}}

If you needed to control the result scores, you could use compound

{
  $search: {
    compound: {
      should: [ 
        {autocomplete: {path: "customerName", query: "foo" }},
        {text: {path: "customerName", query: "foo" , score: { boost: { "value" : 3" }}}}
    ]}}}

In this case, we're using the text operator to split on word boundaries using the lucene.standard analyzer, and boosting those results above. Results from Atlas Search are automatically sorted by score with top results first. Queries are optimized for performance and this query would be done in one pass.

There are a lot of other knobs in the docs to turn depending on your sorting and querying needs (such as using different analyzers, prefix searches, phrase searches, regex, etc).

If you want those kinds of ordering rules I would load up all of your customer names into an application that does the search and perform search & sort entirely in the application. I don't expect even Atlas search to provide this kind of flexibility.

(I don't think the queries you provided achieve the ordering you want either.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM