Mongodb'da büyük / küçük harfe duyarlı olmayan sorgular nasıl yaparım?


93
var thename = 'Andrew';
db.collection.find({'name':thename});

Büyük / küçük harfe duyarlı olmadan nasıl sorgulayabilirim? "Andrew" olsa bile sonuç bulmak istiyorum;



Normal ifadeleri içeren bir yanıt kullanmaya çalışacak herkese bir not: Normal ifadelerin sterilize edilmesi gerekir.
sean

Yanıtlar:


126

Chris Fulstow'un çözümü işe yarayacak (+1), ancak özellikle koleksiyonunuz çok büyükse verimli olmayabilir. Köklü olmayan normal ifadeler (ile ^başlamayanlar, normal ifadeyi dizenin başlangıcına bağlayanlar) ve büyük / iküçük harf duyarlılığı için bayrağı kullananlar, var olsalar bile dizinleri kullanmazlar.

Dikkate alabileceğiniz alternatif bir seçenek de name, örneğin alanın küçük harfli bir sürümünü saklamak için verilerinizi normalleştirmektir name_lower. Daha sonra bunu verimli bir şekilde (özellikle dizine alınmışsa) büyük / küçük harfe duyarlı olmayan tam eşleşmeler için sorgulayabilirsiniz:

db.collection.find({"name_lower": thename.toLowerCase()})

Veya bir önek eşleşmesiyle (köklü bir normal ifade) şu şekilde:

db.collection.find( {"name_lower":
    { $regex: new RegExp("^" + thename.toLowerCase(), "i") } }
);

Bu sorguların her ikisi de bir dizin kullanacaktır name_lower.


1
Harika yanıt, birkaç milyon dokümanı taraması gerektiğinde normal ifade yaklaşımım gerçekten yavaşlıyor.
Chris Fulstow

34
Bu aslında tam olarak doğru değil, çünkü "Andrew" u ararken "Andrew bir şey" bulabilirsin. Bu nedenle normal ifadeyi şuna ayarlayın: new RegExp('^'+ username + '$', "i")tam eşleşme olacak şekilde.
Tarion

9
MongoDB web sitesine göre, büyük / küçük harfe duyarlı olmayan herhangi bir normal ifade endeks açısından verimli değildir "$ regex, bir dizini yalnızca normal ifade bir dizenin başlangıcı (yani ^) için bir çapaya sahipse ve büyük / küçük harfe duyarlı bir eşleşme olduğunda verimli bir şekilde kullanabilir "
Ryan Schumacher

2
Mongoose ile bu benim için çalıştı: User.find ({'username': {$ regex: new RegExp ('^' + username.toLowerCase (), 'i')}}, function (err, res) {if (err ) hata atmak; next (null, res);});
ChrisRich

5
Normal ifadelerle çalışırken isimden kaçmayı asla unutmayın. Enjeksiyonların mongodbun güzelliğini ele geçirmesini istemiyoruz. Bu kodu bir giriş sayfası için kullandığınızı ve kullanıcı adının olduğunu hayal edin ".*".
Tobias

90

Bunun için büyük / küçük harfe duyarlı olmayan bir normal ifade kullanmanız gerekir , ör.

db.collection.find( { "name" : { $regex : /Andrew/i } } );

thenameDeğişkeninizden normal ifade desenini kullanmak için yeni bir RegExp nesnesi oluşturun:

var thename = "Andrew";
db.collection.find( { "name" : { $regex : new RegExp(thename, "i") } } );

Güncelleme: Tam eşleşme için normal ifadeyi kullanmalısınız "name": /^Andrew$/i. Yannick L.


7
Bunu Node.js mongoose kullanarak nasıl yapacağınızı biliyor musunuz?
user847495

1
Bunun büyük koleksiyonlarla ne kadar işe yarayacağını merak ediyorum. Bir çeşit functinon faydasını gevşek ediyorum
Wilfred Springer

5
Bu yanlış, sadece eşit değil, "andrew" içeren herhangi bir belgeyle eşleşecek name.
Jonathan Cremin

14
@JonathanCremin, insanlara doğru cevabı göndermeniz için yardımcı olmak için:{ "name": /^Andrew$/i }
Yannick Loriot

@YannickL. Sağduyu yapmak için 1+. Sadece aradığım şeyi geçip gidiyordum.
Lpc_dark

38

Ben bunu böyle çözdüm.

 var thename = 'Andrew';
 db.collection.find({'name': {'$regex': thename,$options:'i'}});

'Büyük / küçük harfe duyarlı olmayan tam eşleme' ile ilgili sorgulama yapmak istiyorsanız, o zaman böyle gidebilirsiniz.

var thename =  '^Andrew$';
db.collection.find({'name': {'$regex': thename,$options:'i'}});

7

MongoDB 3.4 artık, büyük veri kümelerinde büyük / küçük harfe duyarlı olmayan aramaların hızını önemli ölçüde artıracak gerçek bir büyük / küçük harf duyarlı dizin oluşturma yeteneğini içeriyor. 2 kuvvetinde bir harmanlama belirtilerek yapılır.

Muhtemelen bunu yapmanın en kolay yolu, veritabanı üzerinde bir harmanlama ayarlamaktır. Sonra tüm sorgular bu harmanlamayı devralır ve onu kullanır:

db.createCollection("cities", { collation: { locale: 'en_US', strength: 2 } } )
db.names.createIndex( { city: 1 } ) // inherits the default collation

Bunu şu şekilde de yapabilirsiniz:

db.myCollection.createIndex({city: 1}, {collation: {locale: "en", strength: 2}});

Ve bunu şu şekilde kullanın:

db.myCollection.find({city: "new york"}).collation({locale: "en", strength: 2});

Bu, "new york", "New York", "New york" vb. Adlı şehirleri döndürür.

Daha fazla bilgi için: https://jira.mongodb.org/browse/SERVER-90


güç: 1, büyük / küçük harfe duyarlı olmayan, aksanlara duyarlı olmayan dizin oluşturma için yeterlidir. docs.mongodb.com/manual/reference/collation
Gaurav Ragtah

7
  1. Mongoose (ve Node) ile bu işe yaradı:

    • User.find({ email: /^name@company.com$/i })

    • User.find({ email: new RegExp(`^ $ {emailVariable} $", 'i')})

  2. MongoDB'de bu işe yaradı:

    • db.users.find({ email: { $regex: /^name@company.com$/i }})

Her iki satır da büyük / küçük harf duyarlıdır. DB'deki e-posta olabilir NaMe@CompanY.Comve her iki satır da DB'deki nesneyi bulmaya devam eder.

Aynı şekilde kullanabilirdik /^NaMe@CompanY.Com$/ive yine de e-postayı bulabilirdi: name@company.comDB'de.



4

Bu sorunu birkaç saat önce çözdüm.

var thename = 'Andrew'
db.collection.find({ $text: { $search: thename } });
  • Bu şekilde sorgular yapılırken, büyük / küçük harf duyarlılığı ve aksan duyarlılığı varsayılan olarak yanlış olarak ayarlanır.

Hatta Andrew'un kullanıcı nesnesinden ihtiyacınız olan alanları seçerek bunu şu şekilde yaparak genişletebilirsiniz:

db.collection.find({ $text: { $search: thename } }).select('age height weight');

Referans: https://docs.mongodb.org/manual/reference/operator/query/text/#text


1
$ text, bir metin indeksi ile indekslenmiş alanların içeriği üzerinde bir metin araması gerçekleştirir.
SSH Bu

4

... NodeJS'deki firavun faresi ile:

const countryName = req.params.country;

{ 'country': new RegExp(`^${countryName}$`, 'i') };

veya

const countryName = req.params.country;

{ 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } };

// ^australia$

veya

const countryName = req.params.country;

{ 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } };

// ^turkey$

Javascript, MongoDB üzerinde Mongoose ORM ile NodeJS'de bir tam kod örneği

// get all customers that given country name
app.get('/customers/country/:countryName', (req, res) => {
    //res.send(`Got a GET request at /customer/country/${req.params.countryName}`);

    const countryName = req.params.countryName;

    // using Regular Expression (case intensitive and equal): ^australia$

    // const query = { 'country': new RegExp(`^${countryName}$`, 'i') };
    // const query = { 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } };
    const query = { 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } };

    Customer.find(query).sort({ name: 'asc' })
        .then(customers => {
            res.json(customers);
        })
        .catch(error => {
            // error..
            res.send(error.message);
        });
});

1

Aşağıdaki sorgu, gerekli dizeye sahip belgeleri duyarsız olarak ve genel olarak ortaya çıkan belgeleri bulacaktır.

db.collection.find({name:{
                             $regex: new RegExp(thename, "ig")
                         }
                    },function(err, doc) {
                                         //Your code here...
                  });

1

Büyük / küçük harfe duyarlı olmayan değişmez dizeyi bulmak için:

Normal ifade kullanma (önerilir)

db.collection.find({
    name: {
        $regex: new RegExp('^' + name.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i')
    }
});

Küçük harf dizini kullanma (daha hızlı)

db.collection.find({
    name_lower: name.toLowerCase()
});

Normal ifadeler, değişmez dize eşlemesinden daha yavaştır. Ancak, ek bir küçük harf alanı kod karmaşıklığınızı artıracaktır. Şüpheye düştüğünüzde normal ifadeler kullanın. Yalnızca alanınızın yerini alabilecekse açıkça küçük harfli bir alan kullanmanızı öneririm, yani ilk etapta durumu umursamıyorsanız.

Normal ifadeden önce addan çıkmanız gerekeceğini unutmayın. Kullanıcı girdisi joker karakterlerini .replace(/%/g, '.*')istiyorsanız, "a" ile başlayan tüm adları bulmak için "a%" ile eşleşebilmeniz için çıkıştan sonra eklemeyi tercih edin .


1

Büyük / Küçük Harfe Duyarlı Dizinleri kullanabilirsiniz :

Aşağıdaki örnek, varsayılan harmanlama içermeyen bir koleksiyon oluşturur, ardından ad alanına büyük / küçük harfe duyarlı olmayan bir harmanlama ile bir dizin ekler. Unicode için Uluslararası Bileşenler

/*
* strength: CollationStrength.Secondary
* Secondary level of comparison. Collation performs comparisons up to secondary * differences, such as diacritics. That is, collation performs comparisons of 
* base characters (primary differences) and diacritics (secondary differences). * Differences between base characters takes precedence over secondary 
* differences.
*/
db.users.createIndex( { name: 1 }, collation: { locale: 'tr', strength: 2 } } )

Dizini kullanmak için, sorgular aynı harmanlamayı belirtmelidir.

db.users.insert( [ { name: "Oğuz" },
                            { name: "oğuz" },
                            { name: "OĞUZ" } ] )

// does not use index, finds one result
db.users.find( { name: "oğuz" } )

// uses the index, finds three results
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 2 } )

// does not use the index, finds three results (different strength)
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 1 } )

veya varsayılan harmanlama ile bir koleksiyon oluşturabilirsiniz:

db.createCollection("users", { collation: { locale: 'tr', strength: 2 } } )
db.users.createIndex( { name : 1 } ) // inherits the default collation

-3

$ ToLower'ı aşağıdaki gibi kullanmak kolay bir yol olacaktır.

db.users.aggregate([
    {
        $project: {
            name: { $toLower: "$name" }
        }
    },
    {
        $match: {
            name: the_name_to_search
        }
    }
])
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.