具有多个字段的 Lucene Queryparser
Lucene Queryparser with multiple fields
我使用 Lucene 5.3 并尝试使用 queryparser-syntax 搜索多个字段。我在 Lucene 教程中找到了一个简短示例,并将其修改为版本 5.3 并搜索了这些字段。
package lucenewriterexample;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import java.io.IOException;
public class LuceneWriterExample {
public static void main(String[] args) throws IOException, ParseException {
StandardAnalyzer analyzer = new StandardAnalyzer();
Directory index = new RAMDirectory();
IndexWriterConfig config = new IndexWriterConfig(analyzer);
try (IndexWriter writer = new IndexWriter(index, config)) {
addDoc(writer, "Day first : Lucence Introduction test.", "3436NRX");
addDoc(writer, "Day second , part one : Lucence Projects.", "3437RJ1");
addDoc(writer, "Day second , part two: Lucence Uses testing rr.", "3437RJ2");
addDoc(writer, "Day third : Lucence Demos.", "34338KRX");
}
String querystr = "title:(part) AND course_code:(3437RJ1)";
Query q = new QueryParser("title", analyzer).parse(querystr);
// 3. searching
int hitsPerPage = 10;
IndexReader reader = DirectoryReader.open(index);
IndexSearcher searcher = new IndexSearcher(reader);
TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage);
searcher.search(q, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;
// 4. display results
System.out.println("Query string: " + querystr );
System.out.println("Found " + hits.length + " hits.");
for (int i = 0; i < hits.length; ++i) {
int docId = hits[i].doc;
Document d = searcher.doc(docId);
System.out.println((i + 1) + ". " + d.get("course_code") + "\t" + d.get("title"));
}
// Finally , close reader
}
private static void addDoc(IndexWriter w, String title, String courseCode) throws IOException {
Document doc = new Document();
doc.add(new TextField ("title", title, Field.Store.YES));
doc.add(new StringField("course_code", courseCode, Field.Store.YES));
w.addDocument(doc);
}
queryparser 正在为 "title:part" 工作,然后我得到所有包含 "part" 的文档,但如果我使用 "title:(part) AND course_code:(3437RJ1)" 或“title:(part) OR course_code :(3436NRX) 结果为 0。
搜索错误在哪里?
我 运行 这个并尝试了 title:(part) OR course_code:(3436NRX)
,我得到了 2 个结果,完全符合我的预期。也许您的意思是您期待与 course_code 匹配的第三个结果,但没有得到它。如果你真的是说你实际上得到了 零 结果,我不确定问题是什么。
那么,为什么您无法在 course_code 上找到匹配项?
就像 lucene 经常发生的情况一样,您的分析器不匹配。您的查询解析器正在使用 StandardAnalyzer
,但 course_code 是 StringField
,因此根本没有对其进行分析。 StandardAnalyzer 包含一个将所有内容小写的过滤器,因此最终结果是您有一个包含 3436NRX
的字段和一个 course_code:3436nrx
.
的查询
可能的解决方案是:
- 为您的
StringField
s 使用 TermQuery
而不是查询解析器
- 在将它传递给 lucene
之前,先将您的 course_code 小写
- 使course_code成为
TextField
等等
我使用 Lucene 5.3 并尝试使用 queryparser-syntax 搜索多个字段。我在 Lucene 教程中找到了一个简短示例,并将其修改为版本 5.3 并搜索了这些字段。
package lucenewriterexample;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import java.io.IOException;
public class LuceneWriterExample {
public static void main(String[] args) throws IOException, ParseException {
StandardAnalyzer analyzer = new StandardAnalyzer();
Directory index = new RAMDirectory();
IndexWriterConfig config = new IndexWriterConfig(analyzer);
try (IndexWriter writer = new IndexWriter(index, config)) {
addDoc(writer, "Day first : Lucence Introduction test.", "3436NRX");
addDoc(writer, "Day second , part one : Lucence Projects.", "3437RJ1");
addDoc(writer, "Day second , part two: Lucence Uses testing rr.", "3437RJ2");
addDoc(writer, "Day third : Lucence Demos.", "34338KRX");
}
String querystr = "title:(part) AND course_code:(3437RJ1)";
Query q = new QueryParser("title", analyzer).parse(querystr);
// 3. searching
int hitsPerPage = 10;
IndexReader reader = DirectoryReader.open(index);
IndexSearcher searcher = new IndexSearcher(reader);
TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage);
searcher.search(q, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;
// 4. display results
System.out.println("Query string: " + querystr );
System.out.println("Found " + hits.length + " hits.");
for (int i = 0; i < hits.length; ++i) {
int docId = hits[i].doc;
Document d = searcher.doc(docId);
System.out.println((i + 1) + ". " + d.get("course_code") + "\t" + d.get("title"));
}
// Finally , close reader
}
private static void addDoc(IndexWriter w, String title, String courseCode) throws IOException {
Document doc = new Document();
doc.add(new TextField ("title", title, Field.Store.YES));
doc.add(new StringField("course_code", courseCode, Field.Store.YES));
w.addDocument(doc);
}
queryparser 正在为 "title:part" 工作,然后我得到所有包含 "part" 的文档,但如果我使用 "title:(part) AND course_code:(3437RJ1)" 或“title:(part) OR course_code :(3436NRX) 结果为 0。 搜索错误在哪里?
我 运行 这个并尝试了 title:(part) OR course_code:(3436NRX)
,我得到了 2 个结果,完全符合我的预期。也许您的意思是您期待与 course_code 匹配的第三个结果,但没有得到它。如果你真的是说你实际上得到了 零 结果,我不确定问题是什么。
那么,为什么您无法在 course_code 上找到匹配项?
就像 lucene 经常发生的情况一样,您的分析器不匹配。您的查询解析器正在使用 StandardAnalyzer
,但 course_code 是 StringField
,因此根本没有对其进行分析。 StandardAnalyzer 包含一个将所有内容小写的过滤器,因此最终结果是您有一个包含 3436NRX
的字段和一个 course_code:3436nrx
.
可能的解决方案是:
- 为您的
StringField
s 使用 - 在将它传递给 lucene 之前,先将您的 course_code 小写
- 使course_code成为
TextField
TermQuery
而不是查询解析器
等等