2012-01-30 9 views
5

मैं अपाचे ल्यूसीन का उपयोग करके एक खोजने योग्य फोन/स्थानीय व्यापार निर्देशिका बनाने की कोशिश कर रहा हूं।लुसीन: खोज शब्द के रूप में मल्टी-शब्द वाक्यांश

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

मैं निम्नलिखित के साथ डेटा का अनुक्रमण कर रहा हूँ: पूरे के साथ, पहले

int numberOfHits = 200; 
String LocationOfDirectory = "C:\\dir\\index"; 
TopScoreDocCollector collector = TopScoreDocCollector.create(numberOfHits, true); 
Directory directory = new SimpleFSDirectory(new File(LocationOfDirectory)); 
IndexSearcher searcher = new IndexSearcher(IndexReader.open(directory); 

WildcardQuery q = new WildcardQuery(new Term("Street", "the crescent"); 

searcher.search(q, collector); 
ScoreDoc[] hits = collector.topDocs().scoreDocs; 

मैं एक वाक्यांश क्वेरी के लिए वाइल्डकार्ड क्वेरी की अदला-बदली की कोशिश की है:

String LocationOfDirectory = "C:\\dir\\index"; 

StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_34); 
Directory Index = new SimpleFSDirectory(LocationOfDirectory); 

IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE.34, analyzer); 
IndexWriter w = new IndexWriter(index, config); 


Document doc = new Document(); 
doc.add(new Field("Street", "the crescent", Field.Store.YES, Field.Index.Analyzed); 

w.add(doc); 
w.close(); 

मेरे खोज इस तरह काम करते हैं स्ट्रिंग और फिर सफेद स्थान पर स्ट्रिंग को विभाजित करना और उन्हें एक BooleanQuery में लपेटना:

String term = "the crescent"; 
BooleanQuery b = new BooleanQuery(); 
PhraseQuery p = new PhraseQuery(); 
String[] tokens = term.split(" "); 
for(int i = 0 ; i < tokens.length ; ++i) 
{ 
    p.add(new Term("Street", tokens[i])); 
} 
b.add(p, BooleanClause.Occur.MUST); 

हालांकि, यह काम नहीं किया। मैंने मानक विश्लेषक के बजाय एक कीवर्ड विश्लेषक का उपयोग करने का प्रयास किया, लेकिन फिर अन्य सभी प्रकार की खोजों ने भी काम करना बंद कर दिया। मैंने अन्य पात्रों (+ और @) के साथ रिक्त स्थान बदलने की कोशिश की है, और इस फ़ॉर्म से और प्रश्नों को परिवर्तित कर दिया है, लेकिन यह अभी भी काम नहीं करता है। मुझे लगता है कि यह काम नहीं करता है क्योंकि + और @ विशेष वर्ण हैं जिन्हें अनुक्रमित नहीं किया गया है, लेकिन मुझे ऐसी सूची नहीं मिल रही है, जिनमें से कौन से पात्र इस तरह हैं।

मुझे थोड़ा पागल होना शुरू हो रहा है, क्या किसी को पता है कि मैं क्या गलत कर रहा हूं?

धन्यवाद, रिक

+0

विशेष वर्ण यहां पाया जा सकता: http://lucene.apache.org/core/3_5_0/queryparsersynta x.html # N10180। – Oliver

उत्तर

5

मैंने पाया कि एक QueryParser का उपयोग किए बिना एक प्रश्न उत्पन्न करने के लिए मेरे प्रयास से काम नहीं कर रहा था, इसलिए मैं अपने खुद के प्रश्नों बनाने का प्रयास कर बंद कर दिया और इसके स्थान पर कोई QueryParser इस्तेमाल किया। ऑनलाइन देखे गए सभी अनुशंसाओं से पता चला है कि आपको क्वेरीरीसर में उसी विश्लेषक का उपयोग करना चाहिए जिसका उपयोग आप इंडेक्सिंग के दौरान करते हैं, इसलिए मैंने QueryParser बनाने के लिए मानक विश्लेषक का उपयोग किया।

यह इस उदाहरण पर काम करता है क्योंकि मानक विश्लेषक इंडेक्सिंग के दौरान "क्रेशेंट" सड़क से "द" शब्द को हटा देता है, और इसलिए हम इसकी खोज नहीं कर सकते क्योंकि यह सूचकांक में नहीं है।

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

अंत में, सही समाधान था निम्नलिखित:

int numberOfHits = 200; 
String LocationOfDirectory = "C:\\dir\\index"; 
TopScoreDocCollector collector = TopScoreDocCollector.create(numberOfHits, true); 
Directory directory = new SimpleFSDirectory(new File(LocationOfDirectory)); 
IndexSearcher searcher = new IndexSearcher(IndexReader.open(directory); 

StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_35); 

//WildcardQuery q = new WildcardQuery(new Term("Street", "the crescent"); 
QueryParser qp = new QueryParser(Version.LUCENE_35, "Street", analyzer); 
qp.setDefaultOperator(QueryParser.Operator.AND); 

Query q = qp.parse("grove road"); 

searcher.search(q, collector); 
ScoreDoc[] hits = collector.topDocs().scoreDocs; 
+1

सड़क के नाम से स्टॉप शब्द निकालना गलत है। [दोनों स्ट्रीट] जैसे नामों के बारे में सोचें (http://g.co/maps/r5rnc)। मुझे यकीन है कि आप अधिक ज्वलंत उदाहरण पा सकते हैं। अगर कुछ समझ में नहीं आता तो बस कुछ क्यों हटा दें? –

11

कारण है कि आप अपने दस्तावेज़ों वापस नहीं मिलता है कि जब तक आप का अनुक्रमण StandardAnalyzer उपयोग कर रहे हैं, जो लोअरकेस टोकन धर्मान्तरित और शब्दों को रोकने को दूर करता है। तो आपके उदाहरण के लिए अनुक्रमित होने वाला एकमात्र शब्द 'क्रिसेंट' है। हालांकि, वाइल्डकार्ड प्रश्नों का विश्लेषण नहीं किया जाता है, इसलिए '' 'को क्वेरी के अनिवार्य हिस्से के रूप में शामिल किया गया है। वही आपके परिदृश्य में वाक्यांश प्रश्नों के लिए जाता है।

KeywordAnalyzer शायद आपके उपयोग के मामले के लिए बहुत उपयुक्त नहीं है, क्योंकि यह पूरे क्षेत्र की सामग्री को एक टोकन के रूप में लेता है। आप सड़क क्षेत्र के लिए SimpleAnalyzer का उपयोग कर सकते हैं - यह इनपुट को सभी गैर-अक्षर वर्णों पर विभाजित करेगा और फिर उन्हें लोअरकेस में परिवर्तित करेगा। आप WhitespaceAnalyzerLowerCaseFilter के साथ उपयोग करने पर भी विचार कर सकते हैं। आपको अलग-अलग विकल्पों का प्रयास करने और अपने डेटा और उपयोगकर्ताओं के लिए सबसे अच्छा काम करने की आवश्यकता है।

इसके अलावा, आप क्षेत्र के विभिन्न विश्लेषकों का उपयोग कर सकते हैं (उदा। PerFieldAnalyzerWrapper के साथ) यदि उस क्षेत्र के विश्लेषक बदलते हैं तो अन्य खोजों को तोड़ दिया जाता है।

0

यदि आप एक सटीक शब्द सड़क से मेल खाते हैं, तो आप फील्ड "स्ट्रीट" NOT_ANALYZED सेट कर सकते हैं जो शब्द "द" को फ़िल्टर नहीं करेगा।

doc.add(new Field("Street", "the crescent", Field.Store.YES, Field.Index.Not_Analyzed); 
+1

यह एक अच्छा समाधान नहीं है - इस तरह, आपको परिणाम प्राप्त करने के लिए हमेशा क्वेरी में 'the' शामिल करना होगा। –

+0

@ आर्टूर नोवाक: अपना उत्तर दें। एक उपयुक्त विश्लेषक बिंदु है। –

0

यहां किसी भी Analyzer का उपयोग कर की कोई जरूरत नहीं है coz हाइबरनेट परोक्ष StandardAnalyzer का उपयोग करता है, जिस पर white spaces तो यहाँ समाधान के लिए निर्धारित है आधारित शब्द बंट जाएगा नहीं है AnalyzeNO को यह स्वचालित रूप से प्रदर्शन होगा Multi Phrase Search

@Column(name="skill") 
    @Field(index=Index.YES, analyze=Analyze.NO, store=Store.NO) 
    @Analyzer(definition="SkillsAnalyzer") 
    private String skill; 
संबंधित मुद्दे