【问题标题】:MongoDB - Autocomplete - Get all words starting with XMongoDB - 自动完成 - 获取所有以 X 开头的单词
【发布时间】:2020-06-28 19:22:03
【问题描述】:

我有一个具有以下结构的集合(用户):

{
   propA: {
        words: ["i", "have", "an","important", "question"]
   }
}

我想从数据库中获取自动完成选项,以便在我的网站中输入一些内容。 所以首先,我认为我需要为 propA.words 创建一个索引。 也许是这样的(?):

db.users.createIndex({ "propA.words" : 1 })

其次,我如何查询这个索引以获取所有以 X 开头的单词? 例如,对于字符串“i”,查询将检索 ["i", "important"]。

谢谢!

编辑: 这是合集:

{
    propA: {
        words: ["aa","bb","cc","dd"]
    }
}
{
    propA: {
        words: ["ab"]
    }
}
{
    propA: {
        words: []
    } 
}
{
    propB: []
}

现在,我想要一个查询来获取所有以“a”开头的单词。 查询应在上述集合上返回 ["aa","ab"]。 我希望查询只使用索引,这样搜索才会高效。

【问题讨论】:

  • 您可以使用正则表达式搜索,使用$regex
  • 但是创建索引后,我只是查询用户集合,它会自动使用索引?
  • 是的,当您将该字段用作查询过滤器的一部分时,将使用索引(取决于您的查询过滤器字段和其他索引)。但是,通过正则表达式查询来有效地使用索引,您必须使用 starts with 条件 - { name: { $regex: '^jac' } }。见$regex and index usage
  • 但是我有一个字符串列表,而不是字符串属性

标签: mongodb


【解决方案1】:

您可以使用此聚合,它遍历 words 数组并匹配正则表达式搜索字符串。

db.collection.aggregate( [
  { 
    $addFields: { 
        matches: { 
            $filter: { 
                input: "$propA.words", 
                as: "w",
                cond: {
                    $regexMatch: { input: "$$w" , regex: "^i"  } 
                }
            } 
        } 
    } 
  }
] )

输出:

{
        "_id" : 1,
        "propA" : {
                "words" : [
                        "i",
                        "have",
                        "an",
                        "important",
                        "question"
                ]
        },
        "matches" : [
                "i",
                "important"
        ]
}


[编辑添加]

现在,我想要一个查询来获取所有以“a”开头的单词。这 查询应在上述集合上返回 ["aa","ab"]。我想要 查询只使用索引,这样搜索会很有效。

聚合

db.collection.aggregate( [
  { 
      $match: { "propA.words": { $regex: "^a" } } 
  },
  { 
      $unwind: "$propA.words" 
  },
  { 
      $group: { 
          _id: null, 
          matchedWords: { 
              $addToSet: { 
                  $cond: [ { $regexMatch: { input: "$propA.words", regex: "^a"  } }, 
                            "$propA.words",  
                            "$DUMMY" ] 
              } 
          } 
      } 
  },
  { 
      $project: { _id: 0 } 
  }
] )

结果

{ "matchedWords" : [ "ab", "aa" ] }

索引用法:

在集合上创建索引如下:

db.collection.createIndex( { "propA.words": 1 } )

您可以通过应用explain 并生成一个查询计划验证聚合的$match 阶段的索引使用情况。例如:

db.collection.explain("executionStats").aggregate( [ ... ] )

【讨论】:

  • 但是它只会使用单词 prop 的索引吗?因为聚合在用户集合上
  • 你能解释一下吗?我试图在 mongoshell 中运行这个查询,它会输出整个集合。
  • 是的,没错。它输出整个集合。什么是预期的输出?假设集合中有 3 个包含一些数据的文档,输出会是什么?您期望的输出是什么。请举一个例子,包含三个文档和预期的输出。
  • 感谢它的工作! :) "$DUMMY" 是什么意思?
  • $cond 需要第三个参数。我必须在那里放一些东西(一个虚拟值意味着稍后删除它),所以一个虚拟变量(它不会向数据添加任何东西)。否则,我认为使代码不同。我觉得那是最好的方法,不会在管道中添加太多阶段。
【解决方案2】:

是的,您在字段上创建了一个索引,这是一个数组。然后使用正则表达式查询 - 'starts with' 的符号 ^... 数组字段上的索引会产生很大的负载...但是您的查询是 'start-with' 是一种有效的设计...。

【讨论】:

  • 但是我有一个字符串列表,而不是字符串属性
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多