mongoDB前缀通配符:fulltext-search($ text)查找带有search-string的部分

时间:2014-06-21 15:35:20

标签: mongodb wildcard

我有一个$text-Index的mongodb和这样的元素:

{
   foo: "my super cool item"
}
{
   foo: "your not so cool item"
}

如果我搜索

mycoll.find({ $text: { $search: "super"} })

我得到第一项(正确)。

但我也想用“uper”来搜索第一项 - 但如果我尝试:

mycoll.find({ $text: { $search: "uper"} })

我没有得到任何结果。

我的问题: 如果有一种方法可以使用$ text,那么它会找到搜索字符串的一部分? (例如,如'%uper%'中的mysql

注意:我不要求只进行正则表达式搜索 - 我要求在$ text-search中进行正则表达式搜索!

7 个答案:

答案 0 :(得分:44)

使用$text运算符无法实现。

使用字符串值或字符串数​​组中包含的术语创建文本索引,并且搜索基于这些idex。

您只能对分组进行分组,但不能参与其中。

阅读$text operator referencetext indexes description

答案 1 :(得分:13)

您在第二个示例中尝试执行的操作是在字段mycoll上的集合foo中添加前缀通配符搜索。这不是textsearch功能的设计目标,也不可能使用$text运算符。 This behaviour不包括索引字段中任何给定标记的通配符前缀搜索。但是,您也可以像其他人建议的那样执行正则表达式搜索。这是我的演练:

>db.mycoll.find()
{ "_id" : ObjectId("53add9364dfbffa0471c6e8e"), "foo" : "my super cool item" }
{ "_id" : ObjectId("53add9674dfbffa0471c6e8f"), "foo" : "your not so cool item" }
> db.mycoll.find({ $text: { $search: "super"} })
{ "_id" : ObjectId("53add9364dfbffa0471c6e8e"), "foo" : "my super cool item" }
> db.mycoll.count({ $text: { $search: "uper"} })
0

$text运算符支持搜索单个单词,搜索一个或多个单词或搜索短语。您不希望获得所需的搜索类型

正则表达式解决方案:

> db.mycoll.find({foo:/uper/})
{ "_id" : ObjectId("53add9364dfbffa0471c6e8e"), "foo" : "my super cool item" }
> 

你最后一个问题的答案:在mongoDB中做你想要做的mysql样式%super%

db.mycoll.find( { foo : /.*super.*/ } );

答案 2 :(得分:9)

它应该与/uper/一起使用。

有关详细信息,请参阅http://docs.mongodb.org/manual/reference/operator/query/regex/

修改

根据评论中的要求:

解决方案并不一定意味着实际提供OP 请求的内容,而是他需要解决问题。

由于$regex搜索不适用于文本索引,因此对索引字段进行简单的正则表达式搜索应该会给出预期的结果,但不使用请求的意味着

实际上,这很容易做到:

db.collection.insert( {foo: "my super cool item"} )
db.collection.insert( {foo: "your not so cool item"})
db.collection.ensureIndex({ foo: 1 })
db.collection.find({'foo': /uper/})

给出了预期的结果:

{ "_id" : ObjectId("557f3ba4c1664dadf9fcfe47"), "foo" : "my super cool item" }

补充说明向我们展示了该指数的有效使用:

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "test.collection",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "foo" : /uper/
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "inputStage" : {
                "stage" : "IXSCAN",
                "filter" : {
                    "foo" : /uper/
                },
                "keyPattern" : {
                    "foo" : 1
                },
                "indexName" : "foo_1",
                "isMultiKey" : false,
                "direction" : "forward",
                "indexBounds" : {
                    "foo" : [
                        "[\"\", {})",
                        "[/uper/, /uper/]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        // skipped
    },
    "ok" : 1
}

简而言之:不,您不能重复使用$text索引,但您可以有效地进行查询。就像在Implement auto-complete feature using MongoDB search中写的一样,通过使用map / reduce方法可以更有效率,从索引中消除冗余和不必要的停用词,代价是不再是实时的。

答案 3 :(得分:9)

我没有足够的声誉评论jasenkoh解决方案,但这显然是处理这种情况的最佳方式。

在OP情况下,我会:

db.mycoll.createIndex( { foo: "text" } )
db.mycoll.createIndex( { foo: 1 } )
db.mycoll.find({$or: [{$text: {$search: 'uper'}}, {foo: {$regex: 'uper'}}]})

为了获得更好的表现(但结果略有不同),请将最后一行替换为:

db.mycoll.find({$or: [{$text: {$search: 'uper'}}, {foo: {$regex: '^uper'}}]})

答案 4 :(得分:2)

正如francadaval所说,文字索引是按字词搜索,但如果你合并regextext-index,那么你应该很好。

mycoll.find({$or: [ 
  { 
    $text: {
      $search: "super"
    }
  },
  {
    'column-name': {
      $regex: 'uper',
      $options: 'i'
  }
]})

此外,请确保将正常索引应用于除文本索引之外的列。

答案 5 :(得分:1)

如果您使用正则表达式,则可以搜索“超级酷”而不是“超级商品”,以实现对搜索词的请求做一个或请求$ text和$ regex。

确保同时为文本索引和普通索引编制索引。

答案 6 :(得分:0)

你可能已经实现了 -

db.mycoll.find( {foo: { $regex :  /uper/i  } })

这里'i'是一个选项,表示不区分大小写的搜索