Como consultar o MongoDB com "like"?

1437

Eu quero consultar algo com a likeconsulta do SQL :

SELECT * FROM users  WHERE name LIKE '%m%'

Como faço para conseguir o mesmo no MongoDB? Não consigo encontrar um operador likena documentação .

Vento livre
fonte
7
consulte os documentos do mongodb: Consultas avançadas - Expressões regulares mongodb.org/display/DOCS/…
douyw
7
Sua pergunta tem pelo menos 5votos para a tag de operador like . Posso pedir que você sugira sql-like como sinônimo ?
Caco
3
Este link pode ajudá-lo (a) a goo.gl/gdTYK8
Dilip Kr Singh

Respostas:

1945

Isso teria que ser:

db.users.find({"name": /.*m.*/})

ou similar:

db.users.find({"name": /m/})

Você está procurando algo que contenha "m" em algum lugar (o %operador ' ' do SQL é equivalente ao ' .*' da Regexp ) ', não algo que tenha "m" ancorado no início da string.

nota: o mongodb usa expressões regulares que são mais poderosas que "LIKE" no sql. Com expressões regulares, você pode criar qualquer padrão que imaginar.

Para obter mais informações sobre expressões regulares, consulte este link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

Kyle H
fonte
96
a pesquisa por regex é cara?
Freewind
147
Na verdade, depende. Se a consulta não usar um índice e precisar fazer uma varredura de tabela, certamente poderá ser caro. Se você estiver fazendo uma consulta regex 'começa com', isso poderá usar um índice. É melhor executar uma explicação () para ver o que está acontecendo.
Kyle Banker
35
Quando não está ancorado no início da string, é um pouco caro. Mas, novamente, o mesmo ocorre com uma LIKEconsulta no SQL.
Emily
4
desde que esteja ancorado no início da string, tudo bem? legal então. isso necessidade queremos dizer para adicionar ^
user4951
44
Gostaria de acrescentar regex ijavascript db.users.find({ "name": { $regex: /m/i } })
Doron Segal
368
db.users.insert({name: 'paulo'})
db.users.insert({name: 'patric'})
db.users.insert({name: 'pedro'})

db.users.find({name: /a/})  //like '%a%'

fora: paulo, patric

db.users.find({name: /^pa/}) //like 'pa%' 

fora: paulo, patric

db.users.find({name: /ro$/}) //like '%ro'

fora: pedro

Johnathan Douglas
fonte
bom exemplo! Eu estou achando final cheque com espaço e encontrei este :) / $ /
Phuong
como você encontra todas as entradas para o nome? ou o curinga para * no SQL? Algo que faz select name from users;que apenas lista todos os usuários?
anon58192932
1
@ anon58192932 Para exibir todas as entradas apenas do campo "nome" em uma tabela chamada "usuários", você pode usar o método project () definindo valores dos campos que deseja 1. Os campos que não são mencionados no projeto () não serão buscado, exceto _id. O campo _id é impresso por padrão, que você pode suprimir colocando 0 valor para o método _id dentro do projeto (). Algo como - db.collection.find (). Project ({name: 1, _id: 0}) .toArray (function (err, docs) {console.log (docs); callback (docs);}); Consulte isto - docs.mongodb.com/manual/tutorial/…
gauravparmar 15/02
282

No

  • PyMongo usando Python
  • Mongoose usando Node.js
  • Jongo , usando Java
  • mgo , usando Go

você pode fazer:

db.users.find({'name': {'$regex': 'sometext'}})
Afshin Mehrabani
fonte
2
funciona bem para pesquisa com distinção entre maiúsculas e minúsculas, você poderia me dizer como posso fazê-lo funcionar para executar pesquisa sem distinção entre maiúsculas e minúsculas?
Tahir Yasin 29/03
Qual seria o regex para%sometext%
Tahir Yasin 30/03
64
@TahirYasin se você ainda está se perguntando, busca case-insensitive seria feito da seguinte forma:db.users.find({'name': {'$regex': 'sometext', '$options': 'i'}})
sumowrestler
Eu resolvidos em golang usando mgo simplesmente um código como este, seletor: = bson.M { "técnico": bson.M { "$ regex": tech}}
Sandun Priyanka
1
Sinto que esta deve ser a resposta aceita. É o mais simples e elegante atualmente.
Brett84c
88

No PHP, você pode usar o seguinte código:

$collection->find(array('name'=> array('$regex' => 'm'));
leon
fonte
4
python + mongoengine: people = People.objects.raw_query ({'name': {'$ regex': 'm'}})
panchicore
1
Se o seu valor RegEx se origina da entrada do usuário (por exemplo, um formulário de filtro) e você não deseja que o próprio valor seja considerado como um RegExp, você deve aplicar preg_quote () a ele.
Philipp Rieber
2
Acabei de perceber isso, mas esta é realmente a resposta errada, mesmo que funcione abaixo do ideal, você deve usar o objeto regex BSON real via MongoRegex, $ regex tem problemas de compatibilidade com certos comandos como $ in
Sammaye
Esta sintaxe é útil se o valor é armazenado em uma variável, por isso, a consulta pode ser escrita como (em Ruby):$collection.where(field => {"$regex" => value})
Donny Kurnia
Mas por que você não pode usar literais de matriz?
Alper
53

Você usaria regex para isso no mongo.

por exemplo: db.users.find({"name": /^m/})

Joshua Partogi
fonte
29
Eu acho que isso só mostra documentos com um valor nome que começa com "m"
JackAce
53

Já existem muitas respostas. Estou fornecendo diferentes tipos de requisitos e soluções para pesquisa de strings com regex.

Você pode fazer com o regex que contém a palavra, por exemplo, like. Além disso, você pode usar $options => ipara pesquisa que não diferencia maiúsculas de minúsculas

Contém string

db.collection.find({name:{'$regex' : 'string', '$options' : 'i'}})

Não contém stringapenas regex

db.collection.find({name:{'$regex' : '^((?!string).)*$', '$options' : 'i'}})

Insensível a maiúsculas e minúsculas string

db.collection.find({name:{'$regex' : '^string$', '$options' : 'i'}})

Começar com string

db.collection.find({name:{'$regex' : '^string', '$options' : 'i'}})

Terminar com string

db.collection.find({name:{'$regex' : 'string$', '$options' : 'i'}})

Mantenha isso como marcador e referência para quaisquer outras alterações que você possa precisar.

Somnath Muluk
fonte
37

Você tem 2 opções:

db.users.find({"name": /string/})

ou

db.users.find({"name": {"$regex": "string", "$options": "i"}})

No segundo, você tem mais opções, como "i" nas opções para encontrar o uso de maiúsculas e minúsculas. E sobre a "string", você pode usar como ". String. " (% String%) ou "string. *" (String%) e ". * String) (% string), por exemplo. Você pode usar expressões regulares como você quiser.

Aproveitar!

user3645907
fonte
34

Se você estiver usando o node.js , ele diz que você pode escrever isso:

db.collection.find( { field: /acme.*corp/i } );
//or
db.collection.find( { field: { $regex: 'acme.*corp', $options: 'i' } } );

Além disso , você pode escrever isso:

db.collection.find( { field: new RegExp('acme.*corp', 'i') } );
Eddy
fonte
Sintaxe semelhante em Ruby:collection.where(field => Regexp.new(value))
Donny Kurnia 15/04
24

Você já conseguiu as respostas, mas para combinar regex com insensibilidade a maiúsculas e minúsculas

Você poderia usar a seguinte consulta

db.users.find ({ "name" : /m/i } ).pretty()

O ina /m/iindica caso insensibilidade e .pretty()fornece uma saída mais bonita

The6thSense
fonte
mas o que se eu quiser valor ajustado dinamicamente aqui
KS
@KuldeepKoranga você pode colocar qualquer valor dinâmico no lugar de 'm'. é isso que você quer.
The6thSense
var search="feacebook"então como posso definir abaixo @ The6thSens Sim, mas db.users.find ({ "name" : /search/i } )?
KS
@KuldeepKoranga você atribuiu o valor.
The6thSense
1
@KuldeepKoranga stackoverflow.com/questions/7790811/… isso ajuda?
The6thSense
18

Para Mongoose no Node.js

db.users.find({'name': {'$regex': '.*sometext.*'}})
Aqib Mumtaz
fonte
13

Você pode usar o novo recurso do 2.6 mongodb:

db.foo.insert({desc: "This is a string with text"});
db.foo.insert({desc:"This is a another string with Text"});
db.foo.ensureIndex({"desc":"text"});
db.foo.find({
    $text:{
        $search:"text"
    }
});
cmarrero01
fonte
6
Observe que a pesquisa de texto do AFAIK Mongodb funciona em palavras inteiras apenas por padrão, portanto, isso corresponderá a valores como "Esta é uma string com texto", mas não "Esta é uma string com subtexto". Portanto, não é como o operador "LIKE" do sql.
Rocketmonkeys 10/03/2019
@Rocketmonkeys é verdade ... para algo como "LIKE operator", você usaria o operador $ regex mongo.
Cmarrero01
13

No nodejs project e use mongoose use Like query

var User = mongoose.model('User');

var searchQuery={};
searchQuery.email = req.query.email;
searchQuery.name = {$regex: req.query.name, $options: 'i'};
User.find(searchQuery, function(error, user) {
                if(error || user === null) {
                    return res.status(500).send(error);
                }
                return res.status(200).send(user);
            });
Shaishab Roy
fonte
Como posso usar como consulta? Eu tentei isso, mas não está funcionando:searchQuery.product_name = '/'+req.query.search.value+'/i';
Muhammad Shahzad 10/10
pode tentar como:searchQuery.product_name= {$regex: req.query.search.value, $options: 'i'};
Shaishab Roy
Você salva minha vida, cara. você pode explicar pouco o que é $ regex e $ options?
Muhammad Shahzad
if(req.query.search.value){ searchQuery.product_name = {$regex: req.query.search.value, $options: 'i'}; searchQuery.sale_amount = {$regex: req.query.search.value, $options: 'i'}; searchQuery.sale_person = {$regex: req.query.search.value, $options: 'i'}; searchQuery.department_name = {$regex: req.query.search.value, $options: 'i'}; searchQuery.sale_date = {$regex: req.query.search.value, $options: 'i'}; }você pode ver por que isso não está funcionando?
Muhammad Shahzad
bem $regex: 'value' gerar expressão regular para o seu valor de pesquisa e $options: 'i'significa que não diferencia maiúsculas de minúsculas . Seu código não funcionou por causa do que você usou mesmo valor para a propriedade diferente e que atuam como e condição que não deve cumprir com sua coleção de banco de dados.
Shaishab Roy
12

Para o PHP mongo Like.
Eu tive vários problemas com o php mongo like. Eu descobri que concatenar os parâmetros do regex ajuda em algumas situações o PHP mongo find field começa com . Eu pensei em postar aqui para contribuir com o tópico mais popular

por exemplo

db()->users->insert(['name' => 'john']);
db()->users->insert(['name' => 'joe']);
db()->users->insert(['name' => 'jason']);

// starts with
$like_var = 'jo';
$prefix = '/^';
$suffix = '/';
$name = $prefix . $like_var . $suffix;
db()->users->find(['name' => array('$regex'=>new MongoRegex($name))]);
output: (joe, john)

// contains
$like_var = 'j';
$prefix = '/';
$suffix = '/';
$name = $prefix . $like_var . $suffix;
db()->users->find(['name' => array('$regex'=>new MongoRegex($name))]);

output: (joe, john, jason)
Dap
fonte
Conforme respostas e comentários anteriores, a pesquisa $ text (Index) fornecerá uma solução melhor com o benchmark comparado ao método $ regex corretamente. Para referência, verifique este link stackoverflow.com/questions/10610131/… . É possível implementar $ método de índice de texto com PHP e mongoDB
sankar muniyappa
12

Usar literais de modelo com variáveis ​​também funciona:

{"firstname": {$regex : `^${req.body.firstname}.*` , $options: 'si' }}

besthost
fonte
Esta é uma pesquisa desde o início ex - se "firstname" contiver testlast e se eu pesquisar por "last" não dará resultado.
Vikas Chauhan
11

Com o MongoDB Compass, você precisa usar a sintaxe do modo estrito, como:

{ "text": { "$regex": "^Foo.*", "$options": "i" } }

(No MongoDB Compass, é importante que você use em "vez de ')

maldito
fonte
10

Você pode usar a instrução where para criar qualquer script JS:

db.myCollection.find( { $where: "this.name.toLowerCase().indexOf('m') >= 0" } );

Referência: http://docs.mongodb.org/manual/reference/operator/where/

briba
fonte
9
$whereé altamente ineficiente. Fazer varredura completa da coleção :(
Sushant Gupta
ah, não tem problema, eu estava dizendo assim: D
Sushant Gupta 23/09
10

No SQL, a consulta ' like ' é assim:

select * from users where name like '%m%'

No console do MongoDB, fica assim:

db.users.find({"name": /m/})     // Not JSON formatted

db.users.find({"name": /m/}).pretty()  // JSON formatted

Além disso pretty()método irá em todos os lugares onde produzir estrutura JSON formatada que é mais legível.

MADHAIYAN M
fonte
10

Regex são caros são processo.

Outra maneira é criar um índice de texto e pesquisá-lo usando $search.

Crie um índice de texto dos campos que você deseja tornar pesquisável:

db.collection.createIndex({name: 'text', otherField: 'text'});

Procure uma sequência no índice de texto:

db.collection.find({
  '$text'=>{'$search': "The string"}
})
Ferrugem
fonte
Solução perfeita ... Regex's são muito caros. Trabalhando com um conjunto de dados de documentos de 20m e a diferença de desempenho é muito perceptível (que é um eufemismo)
nivensookharan
1
Na verdade, esta única funciona para palavras inteiras, consulte docs.mongodb.com/manual/core/index-text/#index-entries
Thomas Ebert
8

No Go e o driver mgo:

Collection.Find(bson.M{"name": bson.RegEx{"m", ""}}).All(&result)

em que result é a instância struct do tipo procurado


fonte
2
pls evitar campos não codificadas em literais, que bson:RegEx{Pattern:"m", Options:"i"}em vez
bithavoc
8

Use expressões regulares correspondentes como abaixo. O 'i' mostra insensibilidade ao caso.

var collections = mongoDatabase.GetCollection("Abcd");

var queryA = Query.And(
         Query.Matches("strName", new BsonRegularExpression("ABCD", "i")), 
         Query.Matches("strVal", new BsonRegularExpression("4121", "i")));

var queryB = Query.Or(
       Query.Matches("strName", new BsonRegularExpression("ABCD","i")),
       Query.Matches("strVal", new BsonRegularExpression("33156", "i")));

var getA = collections.Find(queryA);
var getB = collections.Find(queryB);
Shalabh Raizada
fonte
6

Como Query seria como mostrado abaixo

db.movies.find({title: /.*Twelve Monkeys.*/}).sort({regularizedCorRelation : 1}).limit(10);

para scala ReactiveMongo api,

val query = BSONDocument("title" -> BSONRegex(".*"+name+".*", "")) //like
val sortQ = BSONDocument("regularizedCorRelation" -> BSONInteger(1))
val cursor = collection.find(query).sort(sortQ).options(QueryOpts().batchSize(10)).cursor[BSONDocument]
prayagupd
fonte
6

Parece que existem razões para usar o /regex_pattern/padrão javascript e o mongo {'$regex': 'regex_pattern'}. Consulte: Restrições de sintaxe MongoBD RegEx

Este não é um tutorial completo do RegEx, mas fui inspirado a executar esses testes depois de ver uma postagem ambígua altamente votada acima .

> ['abbbb','bbabb','bbbba'].forEach(function(v){db.test_collection.insert({val: v})})

> db.test_collection.find({val: /a/})
{ "val" : "abbbb" }
{ "val" : "bbabb" }
{ "val" : "bbbba" }

> db.test_collection.find({val: /.*a.*/})
{ "val" : "abbbb" }
{ "val" : "bbabb" }
{ "val" : "bbbba" }

> db.test_collection.find({val: /.+a.+/})
{ "val" : "bbabb" }

> db.test_collection.find({val: /^a/})
{ "val" : "abbbb" }

> db.test_collection.find({val: /a$/})
{ "val" : "bbbba" }

> db.test_collection.find({val: {'$regex': 'a$'}})
{ "val" : "bbbba" }
Bruno Bronosky
fonte
5

Se você estiver usando o Spring-Data Mongodb, poderá fazer isso desta maneira:

String tagName = "m";
Query query = new Query();
query.limit(10);        
query.addCriteria(Criteria.where("tagName").regex(tagName));
Vaibhav
fonte
4

Como o shell Mongo suporta regex, isso é completamente possível.

db.users.findOne({"name" : /.*sometext.*/});

Se quisermos que a consulta não diferencie maiúsculas de minúsculas, podemos usar a opção "i", como mostrado abaixo:

db.users.findOne({"name" : /.*sometext.*/i});
sravanthi
fonte
4

Use a pesquisa de substring de agregação (com índice !!!):

db.collection.aggregate([{
        $project : {
            fieldExists : {
                $indexOfBytes : ['$field', 'string']
            }
        }
    }, {
        $match : {
            fieldExists : {
                $gt : -1
            }
        }
    }, {
        $limit : 5
    }
]);
kz_sergey
fonte
agradável! existe uma maneira de combinar todo o documento? ou fazer a estrutura de agregação fazer uma consulta de acompanhamento para fazer isso? No momento, uma partida se parece com:{ "_id" : ObjectId("5aba5ad988385120a01b1ac2"), "fieldExists" : 4 }
Gianfranco P.
em $ fase de projecto apenas projetar o que você quer
Vokail
4

String deepakparmar, dipak, parmar

db.getCollection('yourdb').find({"name":/^dee/})

ans deepakparmar

db.getCollection('yourdb').find({"name":/d/})

ans deepakparmar, dipak

db.getCollection('yourdb').find({"name":/mar$/})

ans deepakparmar, parmar

Deepak parmar
fonte
2

Encontrei uma ferramenta gratuita para traduzir consultas MYSQL para o MongoDB. http://www.querymongo.com/ Verifiquei com várias consultas. como eu vejo quase todos eles estão corretos. De acordo com isso, a resposta é

db.users.find({
    "name": "%m%"
});
Lakmal Vithanage
fonte
2

O MongoRegex foi preterido.
Use MongoDB \ BSON \ Regex

$regex = new MongoDB\BSON\Regex ( '^m');
$cursor = $collection->find(array('users' => $regex));
//iterate through the cursor
Albert s
fonte
É importante notar que isso se refere à classe MongoRegex no PHP . Não é muito relevante para esta questão, que é sobre o Node. Provavelmente deve ser um comentário ou, melhor ainda, uma pergunta auto-respondida em um post separado.
Boaz - Restabelece Monica
2
db.customer.find({"customerid": {"$regex": "CU_00000*", "$options": "i"}}).pretty()

Quando estamos pesquisando padrões de cadeia, sempre é melhor usar o padrão acima como quando não temos certeza sobre o caso. Espero que ajude!!!

priya raj
fonte