mongoDB 前缀通配符:全文搜索 ($text) 查找带有搜索字符串的部分
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24343156/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
mongoDB prefix wildcard: fulltext-search ($text) find part with search-string
提问by mdunisch
I have mongodb with a $text-Index
and elements like this:
我有一个 mongodb$text-Index
和这样的元素:
{
foo: "my super cool item"
}
{
foo: "your not so cool item"
}
If i do search with
如果我搜索
mycoll.find({ $text: { $search: "super"} })
i get the first item (correct).
我得到第一项(正确)。
But i also want to search with "uper" to get the fist item - but if i try:
但我也想用“uper”搜索以获得第一个项目 - 但如果我尝试:
mycoll.find({ $text: { $search: "uper"} })
I dont get any results.
我没有得到任何结果。
My Question:
If there is a way to use $text so its finds results with a part of the searching string? (e.g. like '%uper%'
in mysql
)
我的问题:如果有办法使用 $text 以便它使用搜索字符串的一部分查找结果?(例如像'%uper%'
在mysql
)
Attention: I dont ask for a regex only search - i ask for a regex-search within a $text-search!
注意:我不要求仅进行正则表达式搜索 - 我要求在 $text-search 中进行正则表达式搜索!
采纳答案by francadaval
It's not posible to do it with $text
operator.
用$text
运营商来做是不可能的。
Text indexes are created with the terms included in the string value or in a strings array and the search is based in those idexes.
文本索引是使用包含在字符串值或字符串数组中的术语创建的,并且搜索基于这些 idex。
You can only group terms on a pharse but not take part of them.
您只能在一个词组上对术语进行分组,但不能参与其中。
Read $text
operator referenceand text indexes description.
阅读$text
操作员参考和文本索引说明。
回答by francadaval
What you are trying to do in your second example is prefix wildcard search in your collection mycoll
on field foo
. This is not something the textsearch feature is designed for and it is not possible to do it with $text
operator. This behaviourdoes not include wildcard prefix search on any given token in the indexed field. However you can alternatively perform regex search as others suggested. Here is my walkthrough:
您在第二个示例中尝试做的是mycoll
在 field的集合中搜索前缀通配符foo
。这不是 textsearch 功能的设计目标,并且不可能使用$text
operator来完成。此行为不包括对索引字段中任何给定标记的通配符前缀搜索。但是,您也可以按照其他人的建议执行正则表达式搜索。这是我的演练:
>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
The $text
operator supports search for a single word, search for one or more words or search for phrase. The kind of search you wish is not supported
该$text
操作符支持搜索单个单词、搜索一个或多个单词或搜索短语。不支持您希望的搜索类型
The regex solution:
正则表达式解决方案:
> db.mycoll.find({foo:/uper/})
{ "_id" : ObjectId("53add9364dfbffa0471c6e8e"), "foo" : "my super cool item" }
>
The answer to your final question: to do mysql style %super%
in mongoDB you would most likely have to do:
您最后一个问题的答案:要%super%
在 mongoDB 中执行 mysql 样式,您很可能必须执行以下操作:
db.mycoll.find( { foo : /.*super.*/ } );
回答by Jean-Baptiste Martin
I don't have enough reputation to comment jasenkoh solution, but this is clearly the best way to deal with this situation.
我没有足够的声誉来评论 jasenkoh 解决方案,但这显然是处理这种情况的最佳方式。
In OP situation, I would:
在 OP 情况下,我会:
db.mycoll.createIndex( { foo: "text" } )
db.mycoll.createIndex( { foo: 1 } )
db.mycoll.find({$or: [{$text: {$search: 'uper'}}, {foo: {$regex: 'uper'}}]})
For better performances (but slightly different results), replace the last line with:
为了获得更好的性能(但结果略有不同),请将最后一行替换为:
db.mycoll.find({$or: [{$text: {$search: 'uper'}}, {foo: {$regex: '^uper'}}]})
回答by Markus W Mahlberg
It should work with /uper/
.
它应该与/uper/
.
See http://docs.mongodb.org/manual/reference/operator/query/regex/for details.
有关详细信息,请参阅http://docs.mongodb.org/manual/reference/operator/query/regex/。
Edit:
编辑:
As per request in the comments:
根据评论中的要求:
The solution wasn't necessarily meant to actually give what the OP requested, but what he needed to solve the problem.
该解决方案并不一定意味着实际提供 OP要求的内容,而是他解决问题所需的内容。
Since $regex
searches don't work with text indices, a simple regex search over an indexed field should give the expected result, though not using the requested means.
由于$regex
搜索不适用于文本索引,对索引字段的简单正则表达式搜索应该会给出预期的结果,尽管不使用请求的手段。
Actually, it is pretty easy to do this:
实际上,要做到这一点很容易:
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/})
gives us the expected result:
给了我们预期的结果:
{ "_id" : ObjectId("557f3ba4c1664dadf9fcfe47"), "foo" : "my super cool item" }
An added explain shows us that the index was used efficiently:
添加的解释向我们展示了索引的有效使用:
{
"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
}
To make a long story short: No, you can not reuse a $text
index, but you can do the query efficiently. Like written in Implement auto-complete feature using MongoDB search, one could probably be even more efficient by using a map/reduce approach, eliminating redundancy and unnecessary stop words from the indices, at the cost of being not real time any more.
长话短说:不,你不能重用$text
索引,但你可以有效地进行查询。就像使用 MongoDB 搜索实现自动完成功能中所写的那样,通过使用 map/reduce 方法,从索引中消除冗余和不必要的停用词,可能会更有效,但代价是不再是实时的。
回答by jasenkoh
As francadaval said, text index is searching by terms but if you combine regex
and text-index
you should be good.
正如 francadaval 所说,文本索引是按术语搜索的,但如果你结合起来regex
,text-index
你应该会很好。
mycoll.find({$or: [
{
$text: {
$search: "super"
}
},
{
'column-name': {
$regex: 'uper',
$options: 'i'
}
]})
Also, make sure that you have normal index applied to the column other than text index.
此外,请确保您已将普通索引应用于文本索引以外的列。
回答by Porika Venkatesh
if you go with regex you can achieve search for "super cool" but not "super item", to achieve both request do an or request with $text and $regex for the search term.
如果您使用正则表达式,您可以实现搜索“超级酷”而不是“超级项目”,以实现对搜索词使用 $text 和 $regex 执行或请求的请求。
make sure you index both text indexing and normal indexing to work.
确保您索引文本索引和正常索引工作。
回答by mohit_IBS
You could have achieved is as-
你本可以实现的是-
db.mycoll.find( {foo: { $regex : /uper/i } })
Here 'i' is an option, denotes case-insensitive search
这里'i'是一个选项,表示不区分大小写的搜索