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

mdu*_*sch 46 wildcard mongodb

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

{
   foo: "my super cool item"
}
{
   foo: "your not so cool item"
}
Run Code Online (Sandbox Code Playgroud)

如果我搜索

mycoll.find({ $text: { $search: "super"} })
Run Code Online (Sandbox Code Playgroud)

我得到第一项(正确).

但我也想用"uper"搜索获得第一项 - 但如果我尝试:

mycoll.find({ $text: { $search: "uper"} })
Run Code Online (Sandbox Code Playgroud)

我没有得到任何结果.

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

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

fra*_*val 46

$text运营商合作是不可行的.

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

您只能在分组上对术语进行分组,但不能参与其中.

读取$text运算符引用文本索引描述.

  • 不使用$ text运算符和文本索引. (7认同)
  • 正如我所说,不是与$ text运算符. (6认同)
  • 2年后回到那个话题.有什么变化吗?我的意思是,无法与`$ text`运算符执行子串匹配?@MarkusWMahlberg我确认了@francadaval的答案.您可以使用正则表达式搜索部分匹配,但性能不佳,即使使用阻止COLLSCAN的索引也是如此.:( (2认同)
  • 他是说你做不到,这是正确的解决方案吗? (2认同)
  • 什么是解决方案。我想要全文搜索功能和部分搜索功能 (2认同)

小智 15

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

>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
Run Code Online (Sandbox Code Playgroud)

$text运营商支持搜索一个词,搜索一个或多个单词或搜索词组.不支持您希望的搜索类型

正则表达式解决方案:

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

你最后一个问题的答案:%super%在mongoDB中做你最有可能要做的mysql风格:

db.mycoll.find( { foo : /.*super.*/ } );
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你的详细解答.我想使用$ text-feature,因为"Text Score"和Language-Fields.但我理解@rancadaval形式的答案,$ text只适用于字符串. (2认同)

Jea*_*tin 11

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

在OP情况下,我会:

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

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

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

  • 我们是否有类似的东西也可以与聚合一起使用? (2认同)

Mar*_*erg 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/})
Run Code Online (Sandbox Code Playgroud)

给我们预期的结果:

{ "_id" : ObjectId("557f3ba4c1664dadf9fcfe47"), "foo" : "my super cool item" }
Run Code Online (Sandbox Code Playgroud)

添加的解释向我们展示了索引的有效使用:

{
    "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
}
Run Code Online (Sandbox Code Playgroud)

简而言之:不,您不能重复使用$text索引,但您可以有效地进行查询.就像在使用MongoDB搜索实现自动完成功能一样,通过使用map/reduce方法可以更高效,从索引中消除冗余和不必要的停用词,代价是不再是实时.

  • 另外:这只能与单个字段索引"正常"工作.如果你有`{foo:"text"的索引,bar:"text"}`并想要在它们中搜索你必须使用`.find({$ text:{$ search:query}})`和那么你的答案是行不通的. (4认同)
  • @ zjm555:首先,它可能是OP问题的解决方案.这就是所谓的"创造性解决问题",可能值得一试.;) (2认同)
  • 此查询不能有效地使用索引,必须在最坏的情况下扫描整个集合.使用`explain('executionStats')`找出你自己......或者只看你答案中的索引边界.只有在查询前缀时,此类索引才有效. (2认同)