检查字段是否包含字符串


453

我正在寻找一个运算符,可以让我检查一个字段的值是否包含某个字符串。

就像是:

db.users.findOne({$contains:{"username":"son"}})

那可能吗?

Answers:


692

您可以使用以下代码来实现。

db.users.findOne({"username" : {$regex : ".*son.*"}});

16
请注意,这将无法有效利用索引,并且会扫描所有值以查找匹配项。查看笔记正则表达式
Stennie

7
@Stennie,那么您建议如何有效使用索引并找到子字符串。
蓝天2012年

4
@Vish:如果您的常见用例是字段的自由文本搜索,并且您有大量文档,那么我将标记文本以进行更有效的查询。您可以使用多键进行简单的全文本搜索,或者可以将反向索引构建为单独的集合。对于不频繁搜索或少量文档,扫描完整索引可能是可以接受的(尽管不是最佳的)性能。
Stennie 2012年

98
这是不是有点过分了?您想要的是 db.users.findOne({"username" : {$regex : "son"}});
JamieJag 2014年

3
可能想查看Mongo 2.6中的全文搜索
wprl 2014年

179

由于Mongo Shell支持正则表达式,因此这是完全可能的。

db.users.findOne({"username" : /.*son.*/});

如果我们希望查询不区分大小写,则可以使用“ i”选项,如下所示:

db.users.findOne({"username" : /.*son.*/i});

请参阅:http : //www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-RegularExpressions


1
请提供一个代码段,说明正则表达式在搜索中的用法。答案不仅应包含链接,还应包含更多信息……
maerics 2012年

1
选择的答案对我不起作用,但是这个答案确实有效(我正在通过docker exec命令执行mongo查询),我认为这个应该是选择的答案,因为它似乎更通用。
亚瑟·韦伯org's

5
就像所选答案中的评论一样,我相信db.users.findOne({"username" : /.*son.*/});这也可能是过大的,而正则表达式可能很简单/son/
Arthur Weborg

2
比使用$ regex更简洁的方式
Lionet Chen

4
编辑此内容以使其使用{ username: /son/ }
Wyck

150

https://docs.mongodb.com/manual/reference/sql-comparison/

http://php.net/manual/zh/mongo.sqltomongo.php

的MySQL

SELECT * FROM users WHERE username LIKE "%Son%"

MongoDB

db.users.find({username:/Son/})

8
您的MongoDB回答很好;考虑编辑问题以删除无关的MySQL建议。
Maerics

31
删除所有查询或更改它?最了解SQL的人,它有助于理解MongoDB
Zheng Kai

4
@ZhengKai:您通常应该在此网站上仅使用标记和要求的特定技术直接回答问题。
maerics

98
@maerics我个人发现Zheng包含MySQL非常有用,因为它提供了参考。
Mike Bartlett

50
我还发现SQL参考相关,我认为应该保留。
vikingsteve,

69

从2.4版开始,您可以在要搜索的字段上创建文本索引,并使用$ text运算符进行查询。

首先,创建索引:

db.users.createIndex( { "username": "text" } )

然后,进行搜索:

db.users.find( { $text: { $search: "son" } } )

基准(〜150K文档):

  • 正则表达式(其他答案)=> 5.6-6.9秒
  • 文字搜索=> .164-.201秒

笔记:

  • 集合只能有一个文本索引。如果要搜索任何字符串字段,可以使用通配符文本索引,例如:db.collection.createIndex( { "$**": "text" } )
  • 文本索引可能很大。它为每个插入的文档的每个索引字段中的每个唯一后词形词包含一个索引条目。
  • 与普通索引相比,文本索引的构建时间更长。
  • 文本索引不存储短语或有关文档中单词接近程度的信息。结果,当整个集合放入RAM中时,短语查询将更有效地运行。

14
不,事实上的文本运算符不允许执行“包含”,因此它将仅返回完全匹配的单词,当前从3.0版开始的唯一选项是使用regex,即db.users.find({username:/ son / i} )此查询查找包含“儿子”(不区分大小写)的每个用户
comeGetSome 2015年

3
在集合中添加文档或从集合中删除文档时,是否需要重新编制索引?
杰克·威尔逊

问题的标题为“包含”。全文搜索不适用于该问题。
多纳托

29

由于这是搜索引擎中的首批热门产品之一,并且以上方法似乎都不适用于MongoDB 3.x,因此以下一个有效的正则表达式搜索有效:

db.users.find( { 'name' : { '$regex' : yourvalue, '$options' : 'i' } } )

无需创建和额外的索引等。


1
正则表达式需要清理。
肖恩

16

如果通过Python连接MongoDB,这是您必须做的

db.users.find({"username": {'$regex' : '.*' + 'Son' + '.*'}})

您也可以使用变量名代替“ Son”,因此可以使用字符串连接。


在es2015中,您可以使用反引号{$ regex:.*${value}.*}
Michael Guild

16

完成此任务的最简单方法

如果您希望查询区分大小写

db.getCollection("users").find({'username':/Son/})

如果您希望查询不区分大小写

db.getCollection("users").find({'username':/Son/i})

1
如何在正则表达式中使用变量?
Hisham

4

理想的答案,它的使用索引 i选项不区分大小写

db.users.findOne({"username" : new RegExp(search_value, 'i') });

正则表达式需要清理。
肖恩


1

如何忽略RegExp匹配中的HTML标签:

var text = '<p>The <b>tiger</b> (<i>Panthera tigris</i>) is the largest <a href="https://stackoverflow.com/wiki/Felidae" title="Felidae">cat</a> <a href="https://stackoverflow.com/wiki/Species" title="Species">species</a>, most recognizable for its pattern of dark vertical stripes on reddish-orange fur with a lighter underside. The species is classified in the genus <i><a href="https://stackoverflow.com/wiki/Panthera" title="Panthera">Panthera</a></i> with the <a href="https://stackoverflow.com/wiki/Lion" title="Lion">lion</a>, <a href="https://stackoverflow.com/wiki/Leopard" title="Leopard">leopard</a>, <a href="https://stackoverflow.com/wiki/Jaguar" title="Jaguar">jaguar</a>, and <a href="https://stackoverflow.com/wiki/Snow_leopard" title="Snow leopard">snow leopard</a>. It is an <a href="https://stackoverflow.com/wiki/Apex_predator" title="Apex predator">apex predator</a>, primarily preying on <a href="https://stackoverflow.com/wiki/Ungulate" title="Ungulate">ungulates</a> such as <a href="https://stackoverflow.com/wiki/Deer" title="Deer">deer</a> and <a href="https://stackoverflow.com/wiki/Bovid" class="mw-redirect" title="Bovid">bovids</a>.</p>';
var searchString = 'largest cat species';

var rx = '';
searchString.split(' ').forEach(e => {
  rx += '('+e+')((?:\\s*(?:<\/?\\w[^<>]*>)?\\s*)*)';
});

rx = new RegExp(rx, 'igm');

console.log(text.match(rx));

变成MongoDB聚合过滤器可能很容易。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.