Bir alanın dize içerip içermediğini kontrol etme


454

Bir alanın değeri belirli bir dize içeriyorsa, denetlememe izin veren bir işleç arıyorum.

Gibi bir şey:

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

Mümkün mü?

Yanıtlar:


693

Aşağıdaki kodla yapabilirsiniz.

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

16
Bu edeceğini Not değil tüm değerlerin bir indeksi ve sonucun verimli faydalanmak maçları için taranan. Normal İfadeler ile
Stennie

7
@Stennie, o zaman indeksi verimli kullanmak ve bir alt dize bulmak için ne önerirsiniz.
Blue Sky

4
@ Vish: ortak kullanım durumunuz bir alanda serbest metin araması yapıyorsa ve çok sayıda belgeniz varsa, daha verimli sorgular için metni işaretlerim. Basit bir tam metin araması için multikey'leri kullanabilir veya ayrı bir koleksiyon olarak ters bir dizin oluşturabilirsiniz . Sık olmayan aramalar veya küçük bir belge koleksiyonu için, tam dizinin taranması kabul edilebilir (optimal olmasa da) performans olabilir.
Stennie

98
Bu biraz abartılı değil mi? Ne istiyorsun db.users.findOne({"username" : {$regex : "son"}});
JamieJag


179

Mongo kabuğu regex'i desteklediğinden, bu tamamen mümkündür.

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

Sorgunun büyük / küçük harfe duyarsız olmasını istiyorsak, aşağıda gösterildiği gibi "i" seçeneğini kullanabiliriz:

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

Bkz. Http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-RegularExpressions


1
Lütfen arama için normal ifadelerin kullanımını gösteren bir kod snippet'i ekleyin. Cevaplar sadece bir linkten daha fazla bilgi içermelidir ...
maerics

1
Seçilen cevap benim için çalışmadı, ama bu yaptı (docker exec komutları ile mongo sorguları yürütüyorum) Bence bu daha çok yönlü gibi görünüyor çünkü bu cevap seçilen cevap olmalıdır.
Arthur Weborg

5
seçilen cevaptaki yorumlar gibi ben db.users.findOne({"username" : /.*son.*/});de aşırı olabilir ve normal regex olabilir/son/
Arthur Weborg

2
$ Regex kullanmaktan daha özlü bir yol
Lionet Chen

4
Bunu sadece kullanmak için düzenleyin{ username: /son/ }
Wyck

150

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

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

MySQL

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

MongoDB

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

8
MongoDB cevabınız iyi; alakasız MySQL tavsiyesini kaldırmak için sorunuzu düzenlemeyi düşünün.
maerics

31
Tüm sorgu kaldırılsın mı, değiştirilsin mi? en bilinen insanlar SQL, MongoDB
Zheng Kai

4
@ZhengKai: Bu web sitesinde yalnızca etiketli ve istenen belirli teknolojileri kullanarak soruyu doğrudan doğrudan yanıtlamalısınız.
maerics

98
@maerics şahsen Zheng'in MySQL'i dahil etmesini çok yararlı buldum, çünkü bir referans noktası sağladı.
Mike Bartlett

50
Ayrıca SQL referans ilgili bulundu, ben kalmak gerektiğini düşünüyorum.
vikingsteve

69

Sürüm 2.4'ten itibaren, sorgulamak için $ text operatörünü aramak ve kullanmak için alan (lar) üzerinde bir metin dizini oluşturabilirsiniz .

İlk olarak, dizini oluşturun:

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

Ardından, aramak için:

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

Deneyler (~ 150K belgeler):

  • Normal ifade (diğer yanıtlar) => 5.6-6.9 saniye
  • Metin Arama => .164-.201 saniye

Notlar:

  • Bir koleksiyonun yalnızca bir metin dizini olabilir. Arama yapmak istiyorsanız, bir joker metin dizini de kullanabilirsiniz herhangi böyle, dize alanı: db.collection.createIndex( { "$**": "text" } ).
  • Bir metin dizini büyük olabilir. Girilen her belge için dizine eklenen her alandaki her bir benzersiz, sonradan köklü sözcük için bir dizin girdisi içerir.
  • Metin dizini oluşturmak normal dizinden daha uzun sürer.
  • Metin dizini, sözcüklerdeki belgelere yakınlığıyla ilgili kelime öbeklerini veya bilgileri saklamaz. Sonuç olarak, tüm koleksiyon RAM'e sığdığında ifade sorguları çok daha etkili bir şekilde çalışır.

14
hayır, infact metin operatörü "içerir" i çalıştırmasına izin vermez, bu nedenle yalnızca tam kelime eşleşmesini döndürür, şu anda 3.0'dan beri tek seçenek normal ifade kullanmaktır, yani db.users.find ({username: / son / i} ) bu "son" (case-insenstive) içeren her kullanıcı araması
comeGetSome

3
Koleksiyona belge eklerken veya koleksiyondan belge kaldırırken yeniden dizin oluşturmak zorunda mısınız?
Jake Wilson

Sorunun başlığı "içerir" yazıyor. tam metin araması soru için geçerli değildir.
Donato

29

Bu arama motorlarındaki ilk hitlerden biri olduğu ve yukarıdakilerin hiçbiri MongoDB 3.x için işe yaramadığı için, işleyen bir regex araması:

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

Gerek yok ve ekstra dizin veya benzer.


1
Normal ifadelerin dezenfekte edilmesi gerekir.
sean

16

MongoDB'yi Python üzerinden bağlarsanız yapmanız gerekenler

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

'Son' yerine bir değişken adı ve dolayısıyla dize birleşimi de kullanabilirsiniz.


es2015'te backticks kullanabilirsiniz {$ regex: .*${value}.*}
Michael Guild

16

Bu görevi yerine getirmenin en basit yolu

Sorgunun büyük / küçük harfe duyarlı olmasını istiyorsanız

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

Sorgunun büyük / küçük harfe duyarsız olmasını istiyorsanız

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

1
regex ile değişken nasıl kullanılır ??
Hisham

4

büyük / küçük harfe duyarlı olmayanlar için kullanım indeksi i seçeneği

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

Normal ifadelerin dezenfekte edilmesi gerekir.
sean


1

RegExp eşleşmesinde HTML etiketlerini yoksayma:

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 birleştirme filtresine dönüştürmek muhtemelen çok kolaydır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.