मैं मोंगोडब पर केस-असंवेदनशील प्रश्न कैसे कर सकता हूं?


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

मैं मामले को असंवेदनशील कैसे बना सकता हूं? मैं "andrew" भले ही परिणाम ढूंढना चाहता हूं;



सभी के लिए एक नोट जो रेगेक्स से जुड़े एक उत्तर का उपयोग करने का प्रयास करेगा: रेगेक्स को पवित्रा करने की आवश्यकता है।
शॉन

जवाबों:


126

क्रिस फुलस्टो का समाधान काम करेगा (+1), हालांकि, यह कुशल नहीं हो सकता है, खासकर यदि आपका संग्रह बहुत बड़ा है। गैर-निहित नियमित अभिव्यक्ति (जिनके साथ शुरुआत नहीं होती है ^, जो स्ट्रिंग की शुरुआत के लिए नियमित अभिव्यक्ति को लंगर डालती है), और iकेस असंवेदनशीलता के लिए ध्वज का उपयोग करने वाले लोग अनुक्रमित का उपयोग नहीं करेंगे, भले ही वे मौजूद हों।

एक वैकल्पिक विकल्प जिस पर आप विचार कर सकते हैं वह यह है कि अपने डेटा को nameफ़ील्ड के लोअर-केस संस्करण को संग्रहीत करने के लिए , उदाहरण के लिए name_lower। फिर आप केस-असंवेदनशील सटीक मिलान के लिए उस कुशलता से क्वेरी कर सकते हैं (विशेषकर यदि इसे अनुक्रमित किया गया है):

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

या उपसर्ग मैच (एक नियमित अभिव्यक्ति के रूप में) के साथ:

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

इन दोनों क्वेरीज़ पर एक इंडेक्स का उपयोग किया जाएगा name_lower


1
महान जवाब, मेरा रेगेक्स दृष्टिकोण कुछ मिलियन डॉक्स को स्कैन करने के लिए वास्तव में धीमा हो जाता है।
क्रिस फुल्स्टोव

34
यह वास्तव में पूरी तरह से सही नहीं है, क्योंकि आपको "एंड्रयू" की तलाश में "एंड्रयू कुछ" मिल सकता है। तो new RegExp('^'+ username + '$', "i")एक सटीक मैच होने के लिए रेगेक्स को इसमें समायोजित करें ।
तरियन

9
MongoDB वेबसाइट के अनुसार किसी भी मामले में असंवेदनशील रेगेक्स इंडेक्स कुशल नहीं है "$ रेगेक्स केवल एक इंडेक्स का कुशलता से उपयोग कर सकता है जब नियमित अभिव्यक्ति में स्ट्रिंग की शुरुआत (यानी ^) के लिए एंकर होता है और एक केस-सेंसिटिव मैच होता है "
रेयान शूमाकर

2
Mongoose के साथ इसने मेरे लिए काम किया: User.find ({'उपयोगकर्ता नाम': {$ regex: new RegExp ('^' + username.toLowerCase) (), 'i')}, फ़ंक्शन (ग़लती से, Res) यदि ( ) फेंक दो, अगला (शून्य, Res);});
क्रिसरिच

5
नियमित भाव के साथ काम करते समय नाम से बचना न भूलें। हम चाहते हैं कि मंगोड़ेब की सुंदरता पर इंजेक्शन न लगे। जरा सोचिए आपने इस कोड का उपयोग लॉगिन पेज के लिए किया था और उपयोगकर्ता नाम था ".*"
टोबियास

90

आपको इस एक के लिए केस-असंवेदनशील नियमित अभिव्यक्ति का उपयोग करने की आवश्यकता होगी , जैसे

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

अपने thenameचर से रेगेक्स पैटर्न का उपयोग करने के लिए , एक नया RegExp ऑब्जेक्ट बनाएँ :

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

अपडेट: सटीक मिलान के लिए, आपको रेगेक्स का उपयोग करना चाहिए "name": /^Andrew$/i। यानिक एल के लिए धन्यवाद।


7
क्या आप जानते हैं कि Node.js mongoose का उपयोग कैसे किया जाता है?
user847495

1
मुझे आश्चर्य है कि बड़े संग्रह के साथ यह कितना अच्छा काम करेगा। आप एक तरह के फंक्शनलिन का लाभ ढीला करेंगे
विल्फ्रेड स्प्रिंगर

5
यह गलत है, यह सिर्फ बराबरी के लिए "andrew" युक्त किसी भी दस्तावेज़ से मेल खाएगा name
जोनाथन क्रेमिन

14
@JonathanCremin लोगों की मदद करने के लिए आपको सही उत्तर पोस्ट करना चाहिए:{ "name": /^Andrew$/i }
यानिक लोरीओट

@YannickL। सामान्य ज्ञान की बात करने के लिए 1+। मैं बस वही कर रहा था जो मैं नहीं देख रहा था।
Lpc_dark

38

मैंने इसे इस तरह हल किया है।

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

यदि आप 'केस-इनसेंसिटिव सटीक मैचिंग' पर क्वेरी करना चाहते हैं तो आप इस तरह से जा सकते हैं।

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

7

MongoDB 3.4 में अब एक वास्तविक केस-असंवेदनशील सूचकांक बनाने की क्षमता शामिल है, जो नाटकीय रूप से बड़े डेटासेट पर केस असंवेदनशील लुकअप की गति को बढ़ाएगा। यह 2 की ताकत के साथ टकराव को निर्दिष्ट करके बनाया गया है।

संभवतः ऐसा करने का सबसे आसान तरीका डेटाबेस पर एक कोलाजेशन सेट करना है। तब सभी प्रश्न विरासत में मिलते हैं और इसका उपयोग करेंगे:

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

आप इसे इस तरह भी कर सकते हैं:

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

और इसे इस तरह से उपयोग करें:

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

यह "न्यू यॉर्क", "न्यू यॉर्क", "न्यू यॉर्क", इत्यादि शहरों को लौटाएगा।

अधिक जानकारी के लिए: https://jira.mongodb.org/browse/SERVER-90


शक्ति: 1 केस-असंवेदनशील, डायक्रिटिक-असंवेदनशील अनुक्रमण के लिए पर्याप्त है। docs.mongodb.com/manual/reference/collation
गौरव रागह

7
  1. Mongoose (और Node) के साथ, इसने काम किया:

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

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

  2. MongoDB में, इसने काम किया:

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

दोनों लाइनें केस-असंवेदनशील हैं। DB में ईमेल हो सकता है NaMe@CompanY.Comऔर दोनों लाइनों को अभी भी DB में ऑब्जेक्ट मिलेगा।

इसी तरह, हम उपयोग कर सकते हैं /^NaMe@CompanY.Com$/iऔर यह अभी भी ईमेल मिलेगा: name@company.comDB में।


5

मामले को खोजने के लिए असंवेदनशील स्ट्रिंग का उपयोग करें,

var thename = "Andrew";
db.collection.find({"name":/^thename$/i})

1
आप डुप्लिकेट उत्तर क्यों जोड़ रहे हैं क्योंकि यह पहले से ही stackoverflow.com/a/7101868/4273915 में है
Shrabanee

4

मैंने कुछ घंटे पहले ही इस समस्या को हल किया।

var thename = 'Andrew'
db.collection.find({ $text: { $search: thename } });
  • केस सेंसिटिविटी और डियाक्रिटिक सेंसिटिविटी इस तरह से क्वेश्चन करते समय डिफॉल्ट रूप से झूठी हो जाती हैं।

आप इसे इस तरह से करके एंड्रयू के उपयोगकर्ता वस्तु से अपनी जरूरत के क्षेत्र का चयन करके भी इसका विस्तार कर सकते हैं:

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

संदर्भ: https://docs.mongodb.org/manual/reference/operator/query/text/#text


1
$ पाठ एक पाठ सूचकांक के साथ अनुक्रमित क्षेत्रों की सामग्री पर एक पाठ खोज करता है।
एसएसएच यह

4

... NodeJS पर मानगो के साथ कि प्रश्न:

const countryName = req.params.country;

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

या

const countryName = req.params.country;

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

// ^australia$

या

const countryName = req.params.country;

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

// ^turkey$

जावास्क्रिप्ट में एक पूर्ण कोड उदाहरण, MongoDB पर Mongoose ORM के साथ NodeJS

// 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

निम्नलिखित क्वेरी आवश्यक स्ट्रिंग के साथ दस्तावेजों को असंवेदनशील और वैश्विक घटना के साथ भी पाएगी

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

1

केस-असंवेदनशील शाब्दिक स्ट्रिंग खोजने के लिए:

रेगेक्स (अनुशंसित) का उपयोग करना

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

लो-केस इंडेक्स (तेज़) का उपयोग करना

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

नियमित अभिव्यक्ति शाब्दिक स्ट्रिंग मिलान की तुलना में धीमी हैं। हालाँकि, एक अतिरिक्त लोअरकेस फ़ील्ड आपके कोड की जटिलता को बढ़ाएगा। जब संदेह हो, तो नियमित अभिव्यक्ति का उपयोग करें। मैं केवल एक स्पष्ट रूप से निचले-मामले वाले क्षेत्र का उपयोग करने का सुझाव दूंगा यदि यह आपके क्षेत्र को बदल सकता है, अर्थात, आप पहले मामले में मामले की परवाह नहीं करते हैं।

ध्यान दें कि आपको regex से पहले नाम से बचना होगा। यदि आप उपयोगकर्ता-इनपुट वाइल्डकार्ड चाहते हैं, .replace(/%/g, '.*')तो भागने के बाद आवेदन करना पसंद करें ताकि आप "a" से शुरू होने वाले सभी नामों को खोजने के लिए "एक%" से मिलान कर सकें।


1

आप केस इन्सेंसिटिव इंडेक्स का उपयोग कर सकते हैं :

निम्न उदाहरण कोई डिफ़ॉल्ट टकराव के साथ एक संग्रह बनाता है, फिर नाम क्षेत्र पर एक मामले को असंवेदनशील टकराव के साथ एक सूचकांक जोड़ता है। यूनिकोड के लिए अंतर्राष्ट्रीय घटक

/*
* 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 } } )

इंडेक्स का उपयोग करने के लिए, प्रश्नों को एक ही कोलाज निर्दिष्ट करना होगा।

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 } )

या आप डिफ़ॉल्ट टकराव के साथ एक संग्रह बना सकते हैं:

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

-3

एक आसान तरीका यह होगा कि आप नीचे दिए गए $ टावलर का उपयोग करें।

db.users.aggregate([
    {
        $project: {
            name: { $toLower: "$name" }
        }
    },
    {
        $match: {
            name: the_name_to_search
        }
    }
])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.