在其他字段上使用$ elemMatch进行Mongo DB文本搜索

时间:2018-04-06 07:18:39

标签: mongodb text mongodb-query

我的文档结构如下:

{
  "a": [
    {
      "b": 1,
      "c": "hello world"
    },
    {
      "b": 2,
      "c": "boom!"
    }
  ]
}

我在a.c上有一个文本索引,在a.b

上有一个普通索引

我希望在a.c

上进行过滤时,在a.b上执行文本搜索的查询

我的等效SQL(对不起,这是我熟悉的地方)是:

select * from table where a.b = 1 and a.c like 'hello'

当我对此数据集执行以下mongo查询时,它不会返回预期结果。

db.inventory.find( { "a": { $elemMatch: { b: 1, c: $text: { search: "hello" } } } } )

我并不是真的希望这种方法有效,但也许在mongo受过良好教育的人可以照亮光明

3 个答案:

答案 0 :(得分:2)

$text运算符适用于a.c的任何值,因此......

db.inventory.find({'a.b': 1, $text: { $search: "hello" } })

...将与您提供的文档相匹配。

但是,您对$elemMatch的建议使用建议您希望将这两个谓词应用于a中的每个子文档,以便仅在a.b = 1和<}时返回匹配项strong>兄弟 a.c包含&#34;你好&#34;。

您无法在$text内使用$elemMatch,但您可以像这样使用$regex

db.inventory.find({ a: { $elemMatch: {'b': 1, 'c': { $regex: /^hello/ }}} })

以上命令将查找至少有一个a子文档符合 这些条件的文档:

  • a.b = 1
  • a.c like "hello%"

如果锚定a.c的值,则上述命令甚至会使用索引。因此,如果您可以依赖锚定值,则可以在a.c上停止非文本索引,并且在使用$regex时,您将获得索引的部分文本搜索。

如果你真的必须有一个文本索引(也许你不能依赖于被锚定的值或者你需要阻塞功能)那么搜索必须分为两部分,使用聚合管道:

db.inventory.aggregate([ 
  { $match : { $text: { $search: "hello" } } },
  { $match : { 'a.b': 1 } } 
])

答案 1 :(得分:0)

除了@ glitching之外,您仍然可以将$ regex与$ text一起使用以获得全文索引:

db.inventory.find( { 
    "a": { $elemMatch: { 
        b: 1, 
        c: { $regex: "hello" }
    } } 
    $text: { $search: "hello" }
} )

答案 2 :(得分:-1)

要对MongoDB数据库执行文本搜索,需要在需要搜索文本的字段上创建文本索引。

文本索引有助于在属于MongoDB数据库集合的字段中搜索文本。

根据以上描述,我创建了一个通配符文本索引。

使用通配符文本索引,MongoDB会为包含集合中每个文档的字符串数据的每个字段编制索引。

db.inventory.createIndex( { "$**": "text" } )

要在a.c上执行文本搜索并在a.b上进行过滤,作为解决方案,请在创建文本索引后尝试执行以下MongoDB查找操作到MongoDB shell。

db.inventory.find({
    $text: {
        $search: 'hello'
    },
    a: {
        $elemMatch: {
            b: 1
        }
    }
})
相关问题