原先一直有这个概念,就是在lucene中相关度排序和其他排序是不能组合使用;但是一直怀疑这个观念,我记得是书上看到的(网上也有人这么说),但是有不能确定。
理论上来说,lucene是可以做到这样组合排序的;所以我就试一下了;
- package com.search5173.lucene.demo.sort;
- import java.io.IOException;
- import java.util.HashMap;
- import java.util.Map;
- import org.apache.lucene.analysis.Analyzer;
- import org.apache.lucene.analysis.standard.StandardAnalyzer;
- import org.apache.lucene.document.Document;
- import org.apache.lucene.document.Field;
- import org.apache.lucene.index.CorruptIndexException;
- import org.apache.lucene.index.IndexWriter;
- import org.apache.lucene.index.Term;
- import org.apache.lucene.queryParser.MultiFieldQueryParser;
- import org.apache.lucene.queryParser.ParseException;
- import org.apache.lucene.queryParser.QueryParser;
- import org.apache.lucene.search.IndexSearcher;
- import org.apache.lucene.search.Query;
- import org.apache.lucene.search.ScoreDoc;
- import org.apache.lucene.search.Sort;
- import org.apache.lucene.search.SortField;
- import org.apache.lucene.search.TermQuery;
- import org.apache.lucene.search.TopDocs;
- import org.apache.lucene.store.Directory;
- import org.apache.lucene.store.LockObtainFailedException;
- import org.apache.lucene.store.RAMDirectory;
- import org.apache.lucene.util.Version;
- public class TestLuceneSort {
- public static void main(String args[]) throws CorruptIndexException, LockObtainFailedException, IOException, ParseException {
- try {
- TestLuceneSort.doSearch("天使", 1, 100);
- } catch(Exception ex) {
- // TODO
- }
- }
- public static void doSearch(String keyword, int page, int pageSize) throws CorruptIndexException, LockObtainFailedException, IOException, ParseException
- {
- Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_CURRENT);// Store the index in memory:
- Directory directory = new RAMDirectory();
- // To store an index on disk, use this instead:
- //Directory directory = FSDirectory.open("/tmp/testindex");
- IndexWriter iwriter = new IndexWriter(directory, analyzer, true,
- new IndexWriter.MaxFieldLength(25000));Post post = new Post();
- post.setPostId(10001);
- post.setTitle("校内八大俗天使");
- post.setContent(" 有网友总结校内网类网站的八大俗: 生活常识化妆技,十二星座小秘密; 不看后悔成功录,论文大全雅思题。 恋爱金句传送门,男默女泪蛋疼文; 读到哪句 心痛了?不顶不是中国人。 相关日志推荐不成熟男人的十个标志中国大学排行榜2010版金融危机十项注意2008十大网络公敌将从我们生活里 ");
- iwriter.addDocument(TestLuceneSort.buildDocument(post));
- post.setPostId(10002);
- post.setTitle("冷组天使天使天使天使总是能出这么伟大的冷笑话天使");
- post.setContent(" 鹅李卡|蘑菇蘑菇分享 天使我的某位友邻说:据说大地震前有三个明显征兆: 1.井水异常;2.牲畜反应异常;3.专家出来辟谣。 但是细心网友指出,第二条 和第三条重复了。 然后底下有人回应说:可能是喝了异常的井水。。。 其实专家的嘴就像屁股一样,有图有真相!!!!");
- //post.setContent(" 校内:之前已经有很多关于“天使”的文章了,这些小家伙一举一动往往最能打动我们。今天又收集了一些“天使的眼神”与大家分享,那清澈的眼神是否会直达你 的心底,让你的心也一片清澈? 另外,由于图片数量较多,就作两期发布,希望大家喜欢……");
- iwriter.addDocument(TestLuceneSort.buildDocument(post));
- post.setPostId(10003);
- post.setTitle("冷组天使天使天使天使天使天使天使天使天使天使天使天使天使总是能出这么伟大的冷笑话天使");
- post.setContent(" 鹅李卡|蘑菇蘑菇分享 天使我的某位友邻说:据说大地震前有三个明显征兆: 1.井水异常;2.牲畜反应异常;3.专家出来辟谣。 但是细心网友指出,第二条 和第三条重复了。 然后底下有人回应说:可能是喝了异常的井水。。。 其实专家的嘴就像屁股一样,有图有真相!!!!");
- iwriter.addDocument(TestLuceneSort.buildDocument(post));// Now search the index:
- post.setPostId(10000);
- post.setTitle("冷组天使天使天使天使总是能出这么伟大的冷笑话天使");
- post.setContent(" 鹅李卡|蘑菇蘑菇分享 天使我的某位友邻说:据说大地震前有三个明显征兆: 1.井水异常;2.牲畜反应异常;3.专家出来辟谣。 但是细心网友指出,第二条 和第三条重复了。 然后底下有人回应说:可能是喝了异常的井水。。。 其实专家的嘴就像屁股一样,有图有真相!!!!");
- iwriter.addDocument(TestLuceneSort.buildDocument(post));
- iwriter.close();
- IndexSearcher isearcher = new IndexSearcher(directory, true); // read-only=true
- Map<String, Float> boosts = new HashMap<String, Float>();
- boosts.put("title", 3.0f);
- boosts.put("content", 1.1f);
- QueryParser parser = new MultiFieldQueryParser(Version.LUCENE_CURRENT, new String[]{"title","content"}, analyzer,null);
- Query query = parser.parse(keyword);
- Sort sort1 = new Sort(new SortField[]
- {
- //如果两个都没有注释,那么就是按照先按照相关度,然后按照id排序(相关度相同的情况下)
- SortField.FIELD_SCORE,//注释掉这个就是按照id排序
- new SortField("postId", SortField.INT, false)//注释掉这个就是按照相关度排序
- }
- );
- ScoreDoc[] hits = isearcher.search(query, null, 1000, sort1).scoreDocs;
- System.out.println(hits.length);
- // Iterate through the results:
- for(ScoreDoc match : hits)
- {
- Document doc = isearcher.doc(match.doc);
- System.out.println(""+doc.get("postId") +" : "+doc.get("title") + " sorc:"+match.score);
- }
- isearcher.close();
- directory.close();
- }
- private static Document buildDocument(Post post) {
- Document doc = new Document();
- doc.add(new Field("postId", String.valueOf(post.getPostId()), Field.Store.YES, Field.Index.NOT_ANALYZED));
- doc.add(new Field("title", String.valueOf(post.getTitle()), Field.Store.YES,Field.Index.ANALYZED ));
- doc.add(new Field("content", String.valueOf(post.getContent()), Field.Store.YES,Field.Index.ANALYZED ));
- return doc;
- }
- /**
- * 輸出結果结果
- 相关度
- 10003 : 冷组天使天使天使天使天使天使天使天使天使天使天使天使天使总是能出这么伟大的冷笑话天使 sorc:NaN
- 10002 : 冷组天使天使天使天使总是能出这么伟大的冷笑话天使 sorc:NaN
- 10000 : 冷组天使天使天使天使总是能出这么伟大的冷笑话天使 sorc:NaN
- 10001 : 校内八大俗天使 sorc:NaN
- id
- 10000 : 冷组天使天使天使天使总是能出这么伟大的冷笑话天使 sorc:NaN
- 10001 : 校内八大俗天使 sorc:NaN
- 10002 : 冷组天使天使天使天使总是能出这么伟大的冷笑话天使 sorc:NaN
- 10003 : 冷组天使天使天使天使天使天使天使天使天使天使天使天使天使总是能出这么伟大的冷笑话天使 sorc:NaN
- id+相关度
- 10003 : 冷组天使天使天使天使天使天使天使天使天使天使天使天使天使总是能出这么伟大的冷笑话天使 sorc:NaN
- 10000 : 冷组天使天使天使天使总是能出这么伟大的冷笑话天使 sorc:NaN
- 10002 : 冷组天使天使天使天使总是能出这么伟大的冷笑话天使 sorc:NaN
- 10001 : 校内八大俗天使 sorc:NaN
- */
- }
这里的结论就是在使用相关度排序和其他排序是可以组合使用的,但是我要申明的是一定要把相关度排序的SortField.FIELD_SCORE放前面,否则就是不能组合查询了