使用 mongodb 过滤自动完成

Autocomplete filtered with mongodb

我想在 name 上执行自动完成,但使用 mongoose 和 nodejs 在特定城市进行过滤。 我有一个像这样的 mongodb 集合:

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

到目前为止我做了什么:

我已经设置了 MongoDB 带有搜索索引的地图集(在 search doc 的帮助下) 并像这样设置自动完成:

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});
  }
});

在前端,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,
  });

到目前为止它运行良好。但我不知道如何根据城市过滤自动完成结果。 documentation 好像没有提到这个。有线索吗

像这样使用 compound 运算符,让您以高效的方式更好地控制结果:

"$search": {
  "compound" : {
    "filter" : [{ 
       "text" : { path: "city", query: "New York" } 
     }],
     "must": [{ 
          "autocomplete": {
            "query": `${request.query.term}`,
            "path": "name",
            "fuzzy": {
              "maxEdits": 2,
              "prefixLength": 3,
            },
          },}
        }] }

使用 filter 将过滤您的结果,而不会影响分数。 must 将要求 name 字段也匹配。另请查看 compound 文档中的 shouldmustNot 以获得更多选项。

执行搜索后,使用 aggregation pipeline 中的 $where 管道阶段过滤掉不需要的文档。例如,

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