2016-02-02 3 views
6

हाय मैं अपने संग्रह में व्यक्तियों की तलाश करने के लिए mongoose का उपयोग कर रहा हूं। यदि मुझे खोज के लिए जॉन मैं परिणाम (अगर मैं के लिए खोज जो घटना) प्राप्तआंशिक स्ट्रिंग के साथ मोंगोस टेक्स्ट-सर्च

let regex = new RegExp(QUERY,'i'); 

Person.find({ 
    $or: [ 
     {'name.first': regex}, 
     {'name.last': regex} 
    ] 
}).exec(function(err,persons){ 
    console.log(persons); 
}); 

:

/*Person model*/ 
{ 
    name: { 
     first: String, 
     last: String 
    } 
} 

अब मैं एक प्रश्न के साथ लोगों के लिए खोज करना चाहते हैं। लेकिन अगर मैं जॉन डो खोजता हूं तो मुझे कोई परिणाम स्पष्ट रूप से नहीं मिल रहा है।

तो मैं बदलने क्वेरी केजॉन को | डो मैं परिणाम प्राप्त है, लेकिन यह सभी व्यक्तियों को जो या तो अपने last-/firstname में जॉन या डो है देता है।

अगली बात नेवला textsearch साथ प्रयास करने के लिए किया गया था:

पहले सूचकांक करने के लिए फ़ील्ड जोड़ने:

PersonSchema.index({ 
    name: { 
     first: 'text', 
     last: 'text' 
    } 
},{ 
    name: 'Personsearch index', 
    weights: { 
     name: { 
      first : 10, 
      last: 10 
    } 
} 
}); 

तब व्यक्ति क्वेरी को संशोधित:

Person.find({ 
    $text : { 
     $search : QUERY 
    } 
}, 
{ score:{$meta:'textScore'} }) 
.sort({ score : { $meta : 'textScore' } }) 
.exec(function(err,persons){ 
    console.log(persons); 
}); 

यह सिर्फ ठीक काम करता है! लेकिन अब यह केवल लौटने व्यक्तियों है कि पूरे प्रथम/उपनाम के साथ मेल:

->जॉन रिटर्न मूल्य

->जो रिटर्न का कोई मूल्य नहीं

वहाँ एक रास्ता है इसे हल करने के लिए?

उत्तर बाहरी प्लगइन्स के बिना पसंद किए जाते हैं लेकिन अन्य भी कामना करते हैं।

+0

आपको इसके लिए लोचदार खोज का उपयोग करने की आवश्यकता हो सकती है। यदि आप चाहें तो मैं आपको विस्तृत कोड प्रदान कर सकता हूं। पूर्ण नाम खोज प्राप्त करने के लिए आपको \ "क्वेरी" \ प्रारूप में क्वेरी डालना चाहिए। –

+0

केवल मोंगोज़ के साथ आंशिक खोज करना काम नहीं करता है। मैंने लोचदार के साथ जाने से पहले 3 दिन पहले कोशिश की। –

+0

आपके लिए धन्यवाद संकेत है लेकिन इस मामले के लिए Elastiq थोड़ा अधिक लगता है। यदि पहले और अंतिम नाम को एक फ़ील्ड में विलय करने की संभावना थी (केवल एक क्वेरी के लिए) और फिर रेगेक्स के साथ खोजें यह करेगा। लेकिन मुझे यकीन नहीं है कि क्या मोंगोज़ ऐसा कर सकता है? – Carsten

उत्तर

5

आप एक aggregate पाइपलाइन कि प्रथम और अंतिम नाम concatenates एक साथ $concat का उपयोग कर और फिर से ऐसा कर सकते हैं कि के खिलाफ खोज:

let regex = new RegExp(QUERY,'i'); 

Person.aggregate([ 
    // Project the concatenated full name along with the original doc 
    {$project: {fullname: {$concat: ['$name.first', ' ', '$name.last']}, doc: '$$ROOT'}}, 
    {$match: {fullname: regex}} 
], function(err, persons) { 
    // Extract the original doc from each item 
    persons = persons.map(function(item) { return item.doc; }); 
    console.log(persons); 
}); 

प्रदर्शन चिंता का विषय है, तथापि, के रूप में इस एक सूचकांक उपयोग नहीं कर सकते इसलिए इसे एक पूर्ण संग्रह स्कैन की आवश्यकता होगी।

आप एक $match क्वेरी के साथ $project चरण पूर्ववर्ती कि एक सूचकांक का उपयोग कर सकते डॉक्स के सेट पाइपलाइन के बाकी को देखने की जरूरत है कम करने के लिए द्वारा कि कम कर सकते हैं।

तो यदि आप अलग से name.first और name.last अनुक्रमणिका करते हैं और फिर अपनी खोज स्ट्रिंग का पहला शब्द एक एंकर क्वेरी के रूप में लें (उदा।/^John/i), आप अपने पाइप लाइन की शुरुआत करने के लिए निम्न पहले जोड़ें सकता है:

{$match: $or: [ 
    {'name.first': /^John/i}, 
    {'name.last': /^John/i} 
]} 

जाहिर है आप programmicatically है कि "पहला शब्द" regex उत्पन्न करने के लिए की जरूरत है, लेकिन उम्मीद है कि यह आप के विचार देता है।

1

रेगेक्स आपको इससे मदद कर सकता है।

Person.find({ "name": { "$regex": "Alex", "$options": "i" } }, 
function(err,docs) { 
});