比如说对文档一加了100的boost。那么无论搜什么关键字,这个文档都有可能出现在最前面。这个结果并不是我们期望的效果。
有一个办法可以实现按照关键字的排序。
例如:关键字 玻璃
在这个购买了关键字的公司的相关信息document创建lucene索引时。需要人为的添加一个字段.这个数据与用户发付费有关。而与真实信息无关。
Field field=new Field("玻璃","玻璃 玻璃 玻璃")
field name 为什么这样写,在下面搜索的是就知道了。
document.add(field);
根据lucene score 算法。重复2次的score最高。不过这个score的分值与ANALYZER有关系,不同的ANALYZER重复次数不一样。根据lucene score的算法明显和重复次数不是线性的。
这里是一些测试数据
当关键字是n个字长。ANALYZER=WhitespaceAnalyzer
按照score分值,从高到低 关键字的重复频率应该为 2 5 17 8 11 6 16 20 10 15 19 7 18 14 3 9 4 13 12
如果用WhitespaceAnalyzer,这个频率是固定。不管n个字是什么.
都是这样排列。
import java.io.IOException; import junit.framework.TestCase; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.WhitespaceAnalyzer; 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.IndexWriter.MaxFieldLength; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.Hits; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; 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 com.linkmd.search.constants.XmlConstants; /** * <b>按照购买的关键字来排序</b> * @since 2009-5-7 * @version 1.0 */ public class KeywordSearchTest extends TestCase { private static final Analyzer ANALYZER = new WhitespaceAnalyzer(); private static final String[] PAY_KEY ={ "芯片","大脑","大菠萝","家乐福"}; private static final int comNumber=20; private static final int[][] result=new int[2][comNumber]; /** * @throws Exception */ @SuppressWarnings( { "static-access", "deprecation" }) public void testSearch2() throws Exception { for(int y=0,len=PAY_KEY.length;y<len;y++){ System.out.println("PAY_KEY.length:"+PAY_KEY[y].length()); test(y); System.out.println(); } } private void test(int y) throws CorruptIndexException, LockObtainFailedException, IOException, ParseException { Directory ram = new RAMDirectory(); IndexWriter writer = new IndexWriter(ram, ANALYZER, true, MaxFieldLength.UNLIMITED); for (int i = 0; i <comNumber; i++) { Document doc = new Document(); Field field = new Field("companyName", "公司" + i, Field.Store.YES, Field.Index.NOT_ANALYZED); doc.add(field); /** * 付费字段 关键字设置 */ StringBuilder key = new StringBuilder(); String finalKey = ""; if (i % 1 == 0) { for (int x = 0; x < i; x++) { key.append(this.PAY_KEY[y]); key.append(" "); } finalKey = key.toString(); } Field payField = new Field("pay_key_word", finalKey, Field.Store.YES, Field.Index.ANALYZED); doc.add(payField); writer.addDocument(doc); // System.out.println(doc); } writer.close(); IndexSearcher searcher = new IndexSearcher(ram); QueryParser p = new QueryParser("pay_key_word", ANALYZER); Query q = p.parse(this.PAY_KEY[y]); Hits hits = searcher.search(q); System.out.println("total:"+hits.length()); for (int i = 0, size = hits.length(); i < size; i++) { Document doc = hits.doc(i); int length = doc.getField("pay_key_word").toString().split(" ").length; System.out.print(length+" "); } searcher.close(); } }
现在索引已经建好了。搜索的时候。如果某一个用户输入了玻璃。应该先去数据库查一下,是否这个关键字已经被购买。如果购买了,那么在查询的时刻,我们需要在query的构造上加入
"玻璃":"玻璃"。然后sort数组加上 "玻璃",然后是普通的字段,比如 info 字段的 玻璃 这样查询的顺序就应该按照我们的意思来排序了。
我需要先试试效果。应该可行。
不过其实要实现 关键字 还有很多办法。当然直接结合数据库也可以实现。
社区购物 彤瑶诗佳西兴店正品名牌全场四折