Panduan untuk Penganalisis Lucene

1. Gambaran keseluruhan

Penganalisis Lucene digunakan untuk menganalisis teks semasa mengindeks dan mencari dokumen.

Kami menyebut sebentar penganalisis dalam tutorial pengenalan kami.

Dalam tutorial ini, kita akan membincangkan Penganalisis yang biasa digunakan, bagaimana membina penganalisis tersuai kita dan bagaimana menetapkan penganalisis yang berlainan untuk bidang dokumen yang berbeza .

2. Pergantungan Maven

Pertama, kita perlu menambahkan kebergantungan ini ke pom.xml kami :

 org.apache.lucene lucene-core 7.4.0   org.apache.lucene lucene-queryparser 7.4.0   org.apache.lucene lucene-analyzers-common 7.4.0 

Versi Lucene terkini boleh didapati di sini.

3. Penganalisis Lucene

Penganalisis Lucene membahagikan teks menjadi token.

Penganalisis terutamanya terdiri daripada tokenizer dan penapis. Penganalisis yang berbeza terdiri daripada kombinasi tokenizer dan penapis yang berbeza.

Untuk menunjukkan perbezaan antara penganalisis yang biasa digunakan, kami akan menggunakan kaedah berikut:

public List analyze(String text, Analyzer analyzer) throws IOException{ List result = new ArrayList(); TokenStream tokenStream = analyzer.tokenStream(FIELD_NAME, text); CharTermAttribute attr = tokenStream.addAttribute(CharTermAttribute.class); tokenStream.reset(); while(tokenStream.incrementToken()) { result.add(attr.toString()); } return result; }

Kaedah ini menukar teks yang diberikan menjadi senarai token menggunakan penganalisis yang diberikan.

4. Penganalisis Lucene biasa

Sekarang, mari kita lihat beberapa penganalisis Lucene yang biasa digunakan.

4.1. StandardAnalyzer

Kami akan mulakan dengan StandardAnalyzer yang merupakan penganalisis yang paling biasa digunakan:

private static final String SAMPLE_TEXT = "This is baeldung.com Lucene Analyzers test"; @Test public void whenUseStandardAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new StandardAnalyzer()); assertThat(result, contains("baeldung.com", "lucene", "analyzers","test")); }

Perhatikan bahawa StandardAnalyzer dapat mengenali URL dan e-mel.

Ia juga menghilangkan kata berhenti dan huruf kecil token yang dihasilkan.

4.2. BerhentiAnalisis

The StopAnalyzer terdiri daripada LetterTokenizer, LowerCaseFilter dan StopFilter:

@Test public void whenUseStopAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new StopAnalyzer()); assertThat(result, contains("baeldung", "com", "lucene", "analyzers", "test")); }

Dalam contoh ini, LetterTokenizer membahagikan teks dengan watak bukan huruf, sementara StopFilter membuang kata berhenti dari senarai token.

Namun, tidak seperti StandardAnalyzer , StopAnalyzer tidak dapat mengenali URL.

4.3. SimpleAnalyzer

SimpleAnalyzer terdiri daripada LetterTokenizer dan LowerCaseFilter :

@Test public void whenUseSimpleAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new SimpleAnalyzer()); assertThat(result, contains("this", "is", "baeldung", "com", "lucene", "analyzers", "test")); }

Di sini, SimpleAnalyzer tidak membuang kata berhenti. URL juga tidak mengenali URL.

4.4. Ruang KosongAnalyzer

The WhitespaceAnalyzer kegunaan hanya WhitespaceTokenizer yang berpecah teks oleh watak-watak ruang kosong:

@Test public void whenUseWhiteSpaceAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new WhitespaceAnalyzer()); assertThat(result, contains("This", "is", "baeldung.com", "Lucene", "Analyzers", "test")); }

4.5. Kata KunciAnalyzer

The KeywordAnalyzer tokenizes input ke dalam tanda tunggal:

@Test public void whenUseKeywordAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new KeywordAnalyzer()); assertThat(result, contains("This is baeldung.com Lucene Analyzers test")); }

The KeywordAnalyzer berguna untuk bidang seperti id dan zipcodes.

4.6. Penganalisis Bahasa

Terdapat juga penganalisis khas untuk bahasa yang berbeza seperti EnglishAnalyzer , FrenchAnalyzer dan SpanishAnalyzer :

@Test public void whenUseEnglishAnalyzer_thenAnalyzed() throws IOException { List result = analyze(SAMPLE_TEXT, new EnglishAnalyzer()); assertThat(result, contains("baeldung.com", "lucen", "analyz", "test")); }

Di sini, kami menggunakan EnglishAnalyzer yang terdiri daripada StandardTokenizer , StandardFilter , EnglishPossessiveFilter , LowerCaseFilter , StopFilter , dan PorterStemFilter .

5. Penganalisis Custom

Seterusnya, mari kita lihat bagaimana membina penganalisis tersuai kita. Kami akan membina penganalisis khusus yang sama dengan dua cara yang berbeza.

Dalam contoh pertama, kami akan menggunakan pembangun CustomAnalyzer untuk membina penganalisis kami dari tokenizer dan penapis yang telah ditetapkan :

@Test public void whenUseCustomAnalyzerBuilder_thenAnalyzed() throws IOException { Analyzer analyzer = CustomAnalyzer.builder() .withTokenizer("standard") .addTokenFilter("lowercase") .addTokenFilter("stop") .addTokenFilter("porterstem") .addTokenFilter("capitalization") .build(); List result = analyze(SAMPLE_TEXT, analyzer); assertThat(result, contains("Baeldung.com", "Lucen", "Analyz", "Test")); }

Penganalisis kami sangat mirip dengan EnglishAnalyzer , tetapi sebagai gantinya menggunakan token.

Dalam contoh kedua, kami akan membina penganalisis yang sama dengan melanjutkan Analyzer kelas abstrak dan mengatasi yang createComponents () kaedah :

public class MyCustomAnalyzer extends Analyzer { @Override protected TokenStreamComponents createComponents(String fieldName) { StandardTokenizer src = new StandardTokenizer(); TokenStream result = new StandardFilter(src); result = new LowerCaseFilter(result); result = new StopFilter(result, StandardAnalyzer.STOP_WORDS_SET); result = new PorterStemFilter(result); result = new CapitalizationFilter(result); return new TokenStreamComponents(src, result); } }

Kami juga boleh membuat tokenizer atau penapis khas kami dan menambahkannya ke penganalisis khusus kami jika diperlukan.

Now, let's see our custom analyzer in action – we'll use InMemoryLuceneIndex in this example:

@Test public void givenTermQuery_whenUseCustomAnalyzer_thenCorrect() { InMemoryLuceneIndex luceneIndex = new InMemoryLuceneIndex( new RAMDirectory(), new MyCustomAnalyzer()); luceneIndex.indexDocument("introduction", "introduction to lucene"); luceneIndex.indexDocument("analyzers", "guide to lucene analyzers"); Query query = new TermQuery(new Term("body", "Introduct")); List documents = luceneIndex.searchIndex(query); assertEquals(1, documents.size()); }

6. PerFieldAnalyzerWrapper

Finally, we can assign different analyzers to different fields using PerFieldAnalyzerWrapper.

First, we need to define our analyzerMap to map each analyzer to a specific field:

Map analyzerMap = new HashMap(); analyzerMap.put("title", new MyCustomAnalyzer()); analyzerMap.put("body", new EnglishAnalyzer());

We mapped the “title” to our custom analyzer and the “body” to the EnglishAnalyzer.

Next, let's create our PerFieldAnalyzerWrapper by providing the analyzerMap and a default Analyzer:

PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper( new StandardAnalyzer(), analyzerMap);

Now, let's test it:

@Test public void givenTermQuery_whenUsePerFieldAnalyzerWrapper_thenCorrect() { InMemoryLuceneIndex luceneIndex = new InMemoryLuceneIndex(new RAMDirectory(), wrapper); luceneIndex.indexDocument("introduction", "introduction to lucene"); luceneIndex.indexDocument("analyzers", "guide to lucene analyzers"); Query query = new TermQuery(new Term("body", "introduct")); List documents = luceneIndex.searchIndex(query); assertEquals(1, documents.size()); query = new TermQuery(new Term("title", "Introduct")); documents = luceneIndex.searchIndex(query); assertEquals(1, documents.size()); }

7. Conclusion

We discussed popular Lucene Analyzers, how to build a custom analyzer and how to use a different analyzer per field.

Kod sumber lengkap boleh didapati di GitHub.