如何在文档中的多个对象中进行正则表达式(或文本)搜索

时间:2017-06-21 01:32:16

标签: mongodb mongodb-query

我的MongoDB文档具有如下结构:

{
  "sentence 0":{
              "chunk":["some text",
                     "text",
                     "abc"]
             },  
  "sentence 1":{
              "chunk":["some text",
                     "this is a perfect thing",
                     "abc"]
             }
}

我需要在chunk sentence X的{​​{1}}中找到所有包含“完美”字样的文档。

到目前为止,我得到了这个,这是错误的,因为它甚至没有搜索所有sentence字段。

db.collection.find({"Sentence 0":{ $elemMatch: {"$regex": ".*perfect.*"}}}).limit(10)

1 个答案:

答案 0 :(得分:1)

那些是数组,因此$elemMatch不适用,因为它仅用于实际数组,也用于"多个"标准而不是一个条件。

它们实际上是"子文件"由" key"指定。因此,您的路径必须准确无误:

db.collection.find({ "sentence 1.chunk": { "$regex": ".perfect." }})

如果你想要两条"路径"你需要一个$or

db.collection.find({
  "$or": [
    { "sentence 0.chunk": { "$regex": ".perfect." }},
    { "sentence 1.chunk": { "$regex": ".perfect." }}
  ]
})

为了做到这一点"没有"使用$where在JavaScript逻辑中执行查询的特定路径:

db.collection.find(function() {
  return Object.keys(this).filter(k => /^sentence/).some(k => {
    return this[k].chunk.some(ch => /.*perfect.*/)
  })
})

这两种情况都非常糟糕,因为您正在使用$regex搜索不是"锚定"使用插入符^作为字符串的开头。作为这样一个"完整的集合扫描"执行是为了匹配而不是使用任何可用的索引。相同的约束适用于$where

因此结构不是很好。相反,你应该使用"真正的数组"这可以代表一致的路径"要搜索的数据:

{
  "sentences": [
    {
      "chunk": [ "some text",
                 "text",
                 "abc"
      ]
    },  
      "chunk": [ "some text",
                 "this is a perfect thing",
                 "abc"
      ]
    }
  ]
}

然后我们实际上至少可以在特定路径创建索引和查询:

db.collection.find({
   "sentences.chunk": { "$regex": "^some" }
})

或者"真实的单词"然后实际使用"sentences.chunk"上的文字索引,并使用$text

以有效的方式搜索
db.collection.find({
  "$text": {
    "$search": "something"
  }
})

但是,由于文字搜索的工作原理,当然这与"the""and"之类的内容不匹配。

这一切都取决于你的真实"用例。但是你应该至少避免使用"命名键"来构建文档。哪些有特定路径"因为它们本身就不适合查询目的。

N.B 关键名称中的空格也是不好的做法。它可能看起来像人类可读的#34;但你问的是机器"阅读它比你要求的人类更多?#34;明白它。标签名称与构建数据的方式是分开的。