Lucene-按字段进行搜索,按另一个字段排序,返回到第二个字段
我希望开发一个包含以下字段的简单搜索Lucene-按字段进行搜索,按另一个字段排序,返回到第二个字段,lucene,Lucene,我希望开发一个包含以下字段的简单搜索 头衔 总结 人气 如果有人通过说“ga”来搜索,我会搜索部分匹配的标题(例如“游戏”),并根据受欢迎程度对结果进行排序 如果有
- 头衔
- 总结
- 人气
//创建索引
私有def addDoc(w:IndexWriter,clientContent:clientContent,contentType:String):单位={
val单据:单据=新单据()
添加文档(新文本字段(“title”,clientContent.title,Field.Store.YES))
doc.add(新文本字段(“synopsis”,clientContent.synopsis,Field.Store.YES))
添加文档(新的StringField(“id”,clientContent.id,Field.Store.YES))
添加文档(新的IntField(“流行度”,100000-clientContent.popularity.day,Field.Store.YES))
添加文档(新的StringField(“contentType”,contentType,Field.Store.YES))
w、 添加文档(doc);
}
def createIndex:单位={
index=new-RAMDirectory()
val analyzer=新的标准分析仪(版本.LUCENE_43)
val config=new IndexWriterConfig(Version.LUCENE_43,analyzer)
val w=新的索引编写器(索引,配置)
clientApplication.shows.list.map{addDoc(w,,“Show”)}
w、 关闭()
reader=IndexReader.open(索引)
搜索器=新索引搜索器(读卡器)
}
//按一个字段搜索
def dataSearch(queryString:String,section:String,limit:Int):数组[ScoreDoc]={
val collector=TopFieldCollector.create(
新排序(新SortField(“流行”,SortField.Type.INT,true)),
限制、假、真、真、假);
val analyzer=新的标准分析仪(版本.LUCENE_43)
val q=新的QueryParser(Version.LUCENE_43,section,analyzer).parse(queryString+“*”)
searcher.search(q,收集器)
collector.topDocs().scoreDocs
}
//搜索查询
def搜索(查询字符串:字符串)={
println(s“搜索$queryString”)
val titleResults=dataSearch(查询字符串,“标题”,限制)
if(标题结果长度<限制){
val synopsisResults=数据搜索(查询字符串,“大纲”,限制-标题结果长度)
createModel(标题Results++synopsisResults)
}
其他的
createModel(标题结果)
}
您可以先按分数排序,然后按人气排序,从而大大提高标题查询的效率。只要与标题匹配的所有字段的分数相等,且仅与摘要匹配的文档的分数相等,那么这样做就行了:
Sort mySort=new Sort(SortField.FIELD_分数,new SortField(“popularity”,SortField.Type.INT,true));
当然,他们可能不会平等。只要推进足够大,idf不应该成为问题,但是。。。如果不同文档的字段长度不同,除非禁用了规范,否则lengthNorm将使分数不相等。协调因素将导致问题,因为匹配两个字段的文档将比仅匹配标题的文档得分更高。如果一个匹配项在一个字段中出现不止一次,那么tf将明显不同
因此,您需要一种简化评分的方法,并防止所有花哨的lucene相关性评分逻辑妨碍您。你可以通过使用和获得分数来做你想做的事情
querytitlequery=newconstantscorequery(新前缀查询(新术语(“title”,queryString));
titleQuery.setBoost(2);
Query summaryQuery=new ConstantScoreQuery(新前缀Query(新术语(“title”,queryString));
//结合一个demax,这样匹配两个字段就不会得到比标题更高的分数
Query finalQuery=new DisjnctionMaxQuery(0);
添加(标题查询);
添加(summaryQuery);
Sort mySort=新排序(
SortField.FIELD_得分,
新的SortField(“流行”,SortField.Type.INT,true)
);
val collector=TopFieldCollector.create(mySort、limit、false、true、true、false);
searcher.search(finalQuery,collector);
对于您提供的代码,这将起作用,因为除了构造prefixquery之外,您并不真正需要查询解析器。不过,您也可以保留解析器ConstantScoreQuery
是一个包装查询。您可以同样轻松地包装从QueryParser.parse返回的查询:
QueryParser parser=新的QueryParser(Version.LUCENE_43,“title”,analyzer);
Query titleQuery=new ConstantScoreQuery(parser.parse(queryString+“*”));
titleQuery.SetBoost(2);
Query summaryQuery=new ConstantScoreQuery(parser.parse(“summary:+queryString+“*”));
那么,让我们看看我们第一次尝试添加了什么-它只是原型代码,所以这可能不是最好的方法感谢您的全面回答!这听起来正是我需要的。
"The Game" | "About stuff" | popularity = 3 | (title match)
"Gant charts" | "great stats" | popularity = 7 | (title match)
"Some Title" | "mind the gap" | popularity = 1 | (summary match)
"Another Title" | "blah games" | popularity = 5 | (summary match)
// Creating the indexes
private def addDoc(w:IndexWriter , clientContent: ClientContent, contentType:String):Unit ={
val doc:Document = new Document()
doc.add(new TextField("title", clientContent.title, Field.Store.YES))
doc.add(new TextField("synopsis", clientContent.synopsis, Field.Store.YES))
doc.add(new StringField("id", clientContent.id, Field.Store.YES))
doc.add(new IntField("popularity", 100000 - clientContent.popularity.day, Field.Store.YES))
doc.add(new StringField("contentType", contentType, Field.Store.YES))
w.addDocument(doc);
}
def createIndex: Unit = {
index = new RAMDirectory()
val analyzer = new StandardAnalyzer(Version.LUCENE_43)
val config = new IndexWriterConfig(Version.LUCENE_43, analyzer)
val w = new IndexWriter(index, config)
clientApplication.shows.list.map {addDoc(w, _, "Show")}
w.close()
reader = IndexReader.open(index)
searcher = new IndexSearcher(reader)
}
// Searching by one field
def dataSearch(queryString: String, section:String, limit:Int):Array[ScoreDoc] = {
val collector = TopFieldCollector.create(
new Sort(new SortField("popularity", SortField.Type.INT, true)),
limit,false,true, true, false);
val analyzer = new StandardAnalyzer(Version.LUCENE_43)
val q = new QueryParser(Version.LUCENE_43, section, analyzer).parse(queryString+"*")
searcher.search(q, collector)
collector.topDocs().scoreDocs
}
// Searching for a query
def search(queryString:String) = {
println(s"search $queryString")
val titleResults = dataSearch(queryString, "title", limit)
if (titleResults.length < limit) {
val synopsisResults = dataSearch(queryString, "synopsis", limit - titleResults.length)
createModel(titleResults ++ synopsisResults)
}
else
createModel(titleResults)
}