【问题标题】:MongoDB Atlas Search - Multiple terms in search-string with 'and' condition (not 'or')MongoDB Atlas Search - 搜索字符串中带有“和”条件的多个术语(不是“或”)
【发布时间】:2021-02-02 07:31:54
【问题描述】:

在 MongoDB Atlas 搜索的文档中,autocomplete 运算符如下所述:

query:要搜索的字符串或字符串。如果有多个术语 一个字符串,Atlas Search 还会为 单独的字符串。

对于text 运算符,同样适用:

query:要搜索的一个或多个字符串。如果有多个 字符串中的术语,Atlas Search 还会查找每个术语的匹配项 分别在字符串中。

匹配每个术语单独对我来说似乎很奇怪。我们需要在我们的应用程序中进行多次搜索,对于每次搜索,我们希望您输入的字数越多,结果就越少。

示例:搜索“John Doe”时,我只希望搜索结果同时包含“John”“Doe”。目前,我得到的结果与“John”“Doe”匹配。

这不能使用 MongoDB Atlas Search,还是我做错了什么?


更新 目前,我已经通过在空格 (' ') 上拆分搜索词并将每个单独的关键字添加到单独的 must-sub 子句(使用复合运算符)来解决它。但是,如果有一个关键字只有一个字符,则搜索查询将不再返回任何结果。考虑到这一点,我将一个字符的关键字与多个字符的关键字分开。 下面的 sn-p 有效,但为此我需要在每个文档上保存两个生成的字段:

  • searchString:连接所有可搜索字段的字符串。 F.e. "John Doe Man Streetstreet Citycity"
  • searchArray: 上面的字符串大写&在空格('')上分割成一个数组
const must = [];
const searchTerms = 'John D'.split(' ');
for (let i = 0; i < searchTerms.length; i += 1) {
    if (searchTerms[i].length === 1) {
      must.push({
        regex: {
          path: 'searchArray',
          query: `${searchTerms[i].toUpperCase()}.*`,
        },
      });
    } else if (searchTerms[i].length > 1) {
      must.push({
        autocomplete: {
          query: searchTerms[i],
          path: 'searchString',
          fuzzy: {
            maxEdits: 1,
            prefixLength: 4,
            maxExpansions: 20,
           },
         },
       });
    }
}
db.getCollection('someCollection').aggregate([
  {
    $search: {
      compound: { must },
    },
  },
]).toArray();

更新 2 - 意外行为的完整示例

使用以下文档创建集合:

db.getCollection('testing').insertMany([{
    "searchString": "John Doe ExtraTextHere"
    }, {
    "searchString": "Jane Doe OtherName"
    }, {
    "searchString": "Doem Sarah Thisistestdata"
    }])

在此集合上创建搜索索引“默认”:

{
  "mappings": {
    "dynamic": false,
    "fields": {
      "searchString": {
        "type": "autocomplete"
      }
    }
  }
}

执行以下查询:

db.getCollection('testing').aggregate([
  {
    $search: {
      autocomplete: {
        query: "John Doe",
        path: 'searchString',
        fuzzy: {
          maxEdits: 1,
          prefixLength: 4,
          maxExpansions: 20,
        },
      },
    },
  },
]).toArray();

当用户搜索“John Doe”时,此查询将返回路径“searchString”中包含“John”或“Doe”的所有文档。在此示例中,这意味着所有 3 个文档。用户输入的单词越多,返回的结果就越多。这不是预期的行为。我希望更多的词匹配更少的结果,因为搜索词变得更加精确。

【问题讨论】:

  • 您能分享一个示例查询、结果和示例文档吗?
  • @Nice-Guy 谢谢你的反应。我已经更新了帖子。这些信息是否能说明情况?
  • 这有点帮助。现在,另外两件有用的事情是返回的一些示例文档和相应的索引定义。
  • @Nice-Guy 我再次更新了完整的示例。感谢您的耐心等待!
  • 好的,太好了!谢谢你的坚持。我已经添加了答案。

标签: mongodb search autocomplete mongodb-atlas mongodb-atlas-search


【解决方案1】:

edgeGram 标记化策略可能更适合您的用例,因为它从左到右工作。

试试这个索引定义取自docs:

{
  "mappings": {
    "dynamic": false,
    "fields": {
      "searchString": [
        {
          "type": "autocomplete",
          "tokenization": "edgeGram",
          "minGrams": 3,
          "maxGrams": 10,
          "foldDiacritics": true
        }
      ]
    }
  }
}

另外,添加将查询子句从必须更改为过滤。这将排除不包含所有标记的文档。

【讨论】:

  • 感谢您的建议。我已将索引更改为您的示例,当我对“John Doe”运行相同的搜索查询时,它仍然与 3 个文档匹配。所以它仍然匹配“John”或“Doe”。
  • @Lowie 我又添加了一点,您应该将必须更改为过滤器。你可以试试吗?
  • 我还将设置您的索引并对其进行测试并确保我的建议有效。支持。我明天发帖。
猜你喜欢
  • 2022-09-23
  • 2021-06-01
  • 1970-01-01
  • 2022-06-13
  • 2023-03-20
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多