Search code examples
node.jsmongodbmongooseautocompletemongodb-atlas-search

Autocomplete filtered with mongodb


I would like to perform autocompletion on the name but filtered on a specific city with mongoose and nodejs. I have a mongodb collection like this :

{
    "_id" : ObjectId("6007fd9d984e2507ad452cf3"),
    "name" : "John",
    "city" : "A",
},
{
    "_id" : ObjectId("6007ff6844d9e517e1ec0976"),
    "name" : "Jack",
    "city" : "B",
}

What i have done so far :

I have setup MongoDB Atlas with a Search Index (with the help of search doc) And set up the autocomplete like that :

router.get('/search', async (request, response) => {
  try {
    let result = await Client.aggregate([
      {
        "$search": {
          "autocomplete": {
            "query": `${request.query.term}`,
            "path": "name",
            "fuzzy": {
              "maxEdits": 2,
              "prefixLength": 3,
            },
          },
        },
      },
      {
        $limit: 3
      },
      {
        $project: {
          "_id": 0,
        }
      }
    ]);
    response.send(result);
  } catch (e) {
    response.status(500).send({message: e.message});
  }
});

In front-end, with autocompleteJs :

  const autoCompleteJS = new autoComplete({
    data: {
      src: async () => {
        const query = document.querySelector("#autoComplete").value;
        const source = await fetch(`${window.location.origin}/search?term=${query}`);
        const data = await source.json();
        return data;
      },
      key: ["name"],
    },
    trigger: {
      event: ["input", "focus"],
    },
    searchEngine: "strict",
    highlight: true,
  });

So far it is working well. But I don't know how to make the autocomplete result filtered based on city. It seems that the documentation does not mention this. Do you have any leads.


Solution

  • Use the $where pipeline stage from the aggregation pipeline after performing your search to filter out unwanted documents. So for example,

    Client.aggregate([
      {
        "$search": {
          "autocomplete": {
            "query": `${request.query.term}`,
            "path": "name",
            "fuzzy": {
              "maxEdits": 2,
              "prefixLength": 3,
            },
          },
        },
      },
      { 
        $match: { city: 'city-name' } 
      },
      {
        $limit: 3
      },
      {
        $project: {
          "_id": 0,
        }
      }
    ]);