我有mongodb与$text-Index
和这样的元素:
{
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中进行正则表达式搜索!
用$text
算子不可能做到这一点。
使用字符串值或字符串数组中包含的术语创建文本索引,并且搜索基于这些idex。
您只能在分组上对术语进行分组,但不能参与其中。
您在第二个示例中尝试执行的操作是在字段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.*/ } );
它应该与/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方法可以更有效率,从索引中消除冗余和不必要的停用词,代价是不再是实时的。
我没有足够的声誉来评论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'}}]})
正如francadaval所说,文本索引是按术语搜索,但如果你结合regex
和text-index
你应该是好的。
mycoll.find({$or: [
{
$text: {
$search: "super"
}
},
{
'column-name': {
$regex: 'uper',
$options: 'i'
}
]})
此外,请确保将正常索引应用于除文本索引之外的列。
如果你使用正则表达式,你可以实现搜索“超级酷”而不是“超级项目”,以实现请求执行或请求$ text和$ regex搜索词。
确保您将文本索引和正常索引编入索引。
你可能已经实现了 -
db.mycoll.find( {foo: { $regex : /uper/i } })
这里'i'是一个选项,表示不区分大小写的搜索