LINQ

2012-10-31 9 views
7

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

ID Name 
1  John and Jane Doe 
2  Foo McFoo 
3  Boo McBoo 

यह बहुत आसान एक खोज को लागू करने के लिए जब एक ही नाम प्रत्येक रिकॉर्ड में मौजूद है: उदाहरण के लिए:

var objects = from x in db.Foo 
       where x.Name.Contains("Foo McFoo") 
       select x; 

हालांकि, जब कई नामों से मौजूद हैं, कि दृष्टिकोण काम नहीं करता।

प्रश्न: क्या यह संभव है एक खोज विधि है कि वापसी होगी रिकॉर्ड एक लिखने के लिए (जॉन और जेन डो) जब कोई खोज शब्दों John Doe या Jane Doe का उपयोग करता है?

+0

आप खोज स्ट्रिंग अलग तोड़ने के लिए सफेद स्थान पर एक string.split कर सकता है और तो बस के साथ कई प्रश्नों को चलाएं।सभी परिणाम शामिल हैं और वापस? –

+0

क्या होगा यदि "जॉन स्मिथ" है? क्या आप इसे विभाजित करते हैं और नाम के प्रत्येक भाग की खोज करते हैं? पहला और आखिरी नाम क्या बनाता है? मुझे जो मिल रहा है वह यह है कि वर्तमान स्वरूप में नाम की कोई संरचना नहीं है। – hometoast

उत्तर

3

इस प्रदर्शन को चोट होगा, लेकिन यह कैसे जल्दी से एक के बारे में:

string[] filters = "John Doe".Split(new[] {' '}); 
var objects = from x in db.Foo 
       where filters.All(f => x.Name.Contains(f)) 
       select x; 

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

क्या यह आपके लिए काम करता है?

+0

+1, यह निश्चित रूप से काम करता है! मेरी चिंता 'सभी()' प्रदर्शन है। हो सकता है कि यह मौजूदा डीबी सेटअप को देने का एकमात्र तरीका है। इससे पहले कि मैं ट्रिगर खींचूं, इससे पहले कि मैं इस ट्रिगर को खींचने से पहले समुदाय से प्रतिक्रिया को देखना चाहूंगा ... –

+1

ठीक है, आप बिना किसी मानक खोज (गति डीबी कॉन्फ़िगरेशन और सभी के आधार पर) करेंगे। ऑल() समाधान के साथ, आप औसत पर 2-3 से गुणा करते हैं (यदि नामों में आम तौर पर एक फर्स्टनाम और एक अंतिम नाम होता है)। तो इस मामले में जब आपके पास सटीक मिलान होता है तो आपको स्ट्रिंग को विभाजित नहीं करना पड़ेगा, जो चोट पहुंचाएगा। पहले एक साधारण खोज के साथ कम करने के बारे में और यदि कुछ भी नहीं आता है, तो सभी() बिट का उपयोग करें? बस विचारों को फेंकना – Vladimir

0

आपको या तो कई उपनामों के नाम पर पहले/अंतिम नाम कॉलम में या किसी अन्य तालिका में नाम खींचने की आवश्यकता है।

लेकिन क्या मैं सच में लगता है कि आप Lucene की तरह कुछ इसे देख अगर आप कुछ 'क्षमा' या 'अस्पष्ट'

प्रश्न की आवश्यकता चाहिए: यह एक खोज विधि कि वापसी होगी लिखने के लिए संभव है रिकॉर्ड एक (जॉन और जेन डो) जब कोई खोज शब्द जॉन डो या जेन डो का उपयोग करता है?

अपने प्रश्न का बहुत विशिष्ट होने के लिए, आपको LIKE '%Jane%Doe' को LIKE '%John%Doe' या "जेन डो" के लिए "जॉन डो" में परिवर्तित कर सकते हैं और इस रिकॉर्ड को पुनः प्राप्त होगा। हालांकि मैं "जॉनथन पॉपपाडो" जैसे नामों के साथ समस्याएं देख सकता था।

7

आप एक कस्टम विस्तार विधि "ContainsFuzzy" नाम बना सकते हैं:

public static bool ContainsFuzzy(this string target, string text){ 
    // do the cheap stuff first 
    if (target == text) return true; 
    if (target.Contains(text)) return true; 
    // if the above don't return true, then do the more expensive stuff 
    // such as splitting up the string or using a regex 
} 

फिर अपने LINQ कम से कम पढ़ने के लिए आसान होगा:

var objects = from x in db.Foo 
       where x.Name.ContainsFuzzy("Foo McFoo") 
       select x; 

स्पष्ट नुकसान है कि ContainsFuzzy की प्रत्येक कॉल इसका अर्थ है आपकी विभाजित सूची, आदि को पुनर्निर्मित करना, इसलिए इसमें कुछ ओवरहेड शामिल है।

class FuzzySearch{ 

    private string _searchTerm; 
    private string[] _searchTerms; 
    private Regex _searchPattern; 

    public FuzzySearch(string searchTerm){ 
     _searchTerm = searchTerm; 
     _searchTerms = searchTerm.Split(new Char[] { ' ' }); 
     _searchPattern = new Regex(
      "(?i)(?=.*" + String.Join(")(?=.*", _searchTerms) + ")"); 
    } 

    public bool IsMatch(string value){ 
     // do the cheap stuff first 
     if (_searchTerm == value) return true; 
     if (value.Contains(_searchTerm)) return true; 
     // if the above don't return true, then do the more expensive stuff 
     if (_searchPattern.IsMatch(value)) return true; 
     // etc. 
    } 

} 

आपका LINQ:: आप एक वर्ग FuzzySearch कहा जाता है जो कम से कम तुम कुछ वृद्धि दक्षता देना होगा बना सकते हैं

FuzzySearch _fuzz = new FuzzySearch("Foo McFoo"); 

var objects = from x in db.Foo 
       where _fuzz.IsMatch(x.Name) 
       select x; 
+0

मुझे बहुत मदद की, धन्यवाद! – BjarkeCK

+0

यह होना चाहिए "(? I) (? =। *" + स्ट्रिंग। जॉइन (") (? =। *", _searchTerms) + ")"); – JPVenson

+0

@jpv धन्यवाद - संपादित करें। – JDB

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^