使用 Lucene.NET 为每本书索引多个作者
Index multiple authors per book using Lucene.NET
我正在使用 Lucene.NET 构建超过 1000 万本书的搜索索引。我正在用它来索引一本书:
Document doc = new Document();
doc.Add(new Field("id", bookID, Field.Store.YES, Field.Index.NO));
doc.Add(new Field("publisher", publisherName, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.Add(new Field("title", bookTitle, Field.Store.YES, Field.Index.ANALYZED));
按出版商搜索:
因为我已经用 Index.NOT_ANALYZED
为图书出版商编制了索引,所以我可以使用 high-performance TermsFilter 来做相当于:
SELECT * FROM books WHERE publisher="O'Reilly Media"
按标题搜索:
当然,因为我已经使用 Index.ANALYZED
选项为书名编制了索引,所以我可以使用标准的 QueryParser 来执行以下操作:
SELECT * FROM books WHERE title LIKE "%skating%"
按作者搜索:
但是现在我需要按作者搜索。我需要这样的东西:
SELECT * FROM books WHERE title LIKE "%skating%" AND authors CONTAIN "Jack Black"
那么我该怎么做呢?我每本书都存储了作者姓名和作者 ID。我怎样才能将其索引到 Lucene 文档中,然后按作者快速搜索所有书籍?我不想使用 SQL 因为我需要将搜索关键字与作者过滤器结合起来,所以 Lucene 必须为我进行作者过滤。
最明显的解决方案是:
doc.Add(new Field("authors", "Jack Black; Joan White", Field.Store.YES, Field.Index.ANALYZED));
但这会错误地 return 一位作者的名字是 similar/within 另一位作者的名字的书籍,例如:
- 第 1 本书:作者:Jack D Black、Bob A Smith
- 第 2 册:作者:D 布莱克
所以此时搜索 "D Black" 会错误地 return Book 1 和 Book 2,而不仅仅是 Book 2。因此我需要索引整个作者姓名或 ID(使用 Index.NOT_ANALYZED
),但我每本书需要多个这样的字段。这可能吗?
// can I add the same field multiple times into a document?
doc.Add(new Field("author", "Jack D Black", Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.Add(new Field("author", "Bob A Smith", Field.Store.YES, Field.Index.NOT_ANALYZED));
或者我可以添加作者 ID,以便分析器将每个数字作为一个独立的词:
doc.Add(new Field("authors", "125;1885;23", Field.Store.YES, Field.Index.ANALYZED));
然后使用常规的 Lucene 搜索来查找作者为“125”的所有书籍...这行得通吗,或者这是否还会列出作者为“1254”的书籍?
感谢 Lucas,我认为您可以在索引期间多次添加相同的字段:
foreach (string author in authors){
doc.Add(new Field("author", author, Field.Store.YES, Field.Index.NOT_ANALYZED));
}
这允许您使用高性能的 TermsFilter 来搜索完全匹配。
我正在使用 Lucene.NET 构建超过 1000 万本书的搜索索引。我正在用它来索引一本书:
Document doc = new Document();
doc.Add(new Field("id", bookID, Field.Store.YES, Field.Index.NO));
doc.Add(new Field("publisher", publisherName, Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.Add(new Field("title", bookTitle, Field.Store.YES, Field.Index.ANALYZED));
按出版商搜索:
因为我已经用 Index.NOT_ANALYZED
为图书出版商编制了索引,所以我可以使用 high-performance TermsFilter 来做相当于:
SELECT * FROM books WHERE publisher="O'Reilly Media"
按标题搜索:
当然,因为我已经使用 Index.ANALYZED
选项为书名编制了索引,所以我可以使用标准的 QueryParser 来执行以下操作:
SELECT * FROM books WHERE title LIKE "%skating%"
按作者搜索:
但是现在我需要按作者搜索。我需要这样的东西:
SELECT * FROM books WHERE title LIKE "%skating%" AND authors CONTAIN "Jack Black"
那么我该怎么做呢?我每本书都存储了作者姓名和作者 ID。我怎样才能将其索引到 Lucene 文档中,然后按作者快速搜索所有书籍?我不想使用 SQL 因为我需要将搜索关键字与作者过滤器结合起来,所以 Lucene 必须为我进行作者过滤。
最明显的解决方案是:
doc.Add(new Field("authors", "Jack Black; Joan White", Field.Store.YES, Field.Index.ANALYZED));
但这会错误地 return 一位作者的名字是 similar/within 另一位作者的名字的书籍,例如:
- 第 1 本书:作者:Jack D Black、Bob A Smith
- 第 2 册:作者:D 布莱克
所以此时搜索 "D Black" 会错误地 return Book 1 和 Book 2,而不仅仅是 Book 2。因此我需要索引整个作者姓名或 ID(使用 Index.NOT_ANALYZED
),但我每本书需要多个这样的字段。这可能吗?
// can I add the same field multiple times into a document?
doc.Add(new Field("author", "Jack D Black", Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.Add(new Field("author", "Bob A Smith", Field.Store.YES, Field.Index.NOT_ANALYZED));
或者我可以添加作者 ID,以便分析器将每个数字作为一个独立的词:
doc.Add(new Field("authors", "125;1885;23", Field.Store.YES, Field.Index.ANALYZED));
然后使用常规的 Lucene 搜索来查找作者为“125”的所有书籍...这行得通吗,或者这是否还会列出作者为“1254”的书籍?
感谢 Lucas,我认为您可以在索引期间多次添加相同的字段:
foreach (string author in authors){
doc.Add(new Field("author", author, Field.Store.YES, Field.Index.NOT_ANALYZED));
}
这允许您使用高性能的 TermsFilter 来搜索完全匹配。