首先創建一個簡單的java工程
創建lib目錄并引入jar包
其中IKAnalyzer是一個第三方的中文分詞器
要使用IK分詞器還需要在根目錄下引入幾個文件
IKAnalyzer.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 擴展配置</comment>
<!-- 詞語 -->
<entry key="ext_dict">mydict.dic;</entry>
<!-- 停用詞 -->
<!--<entry key="ext_stopwords">stopword.dic;ext_stopword.dic;</entry>-->
<entry key="ext_stopwords">stopword.dic;</entry>
</properties>
mydict.dic
不是壞人
奧巴馬
普京
斯諾登
stopword.dic
a
an
and
are
as
創建索引存放目錄
基本環境搭建完成
新建一個類 先寫好幾個公用的靜態方法
//索引目錄
public static String indexDir = "D:\\software\\idea-workspace\\lucene\\src\\main\\resources\\index_dir";
//獲取分詞器
private static Analyzer getAnalyzer() {
return new IKAnalyzer();
}
//獲取FSDirectory
private static FSDirectory getFSDirectory() throws IOException {
FSDirectory directory = FSDirectory.open(new File(indexDir));
return directory;
}
//獲取IndexWriter
private static IndexWriter getIndexWriter() throws IOException {
IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, getAnalyzer());
IndexWriter writer = new IndexWriter(getFSDirectory(), conf);
return writer;
}
接下來做簡單增刪查改操作
創建索引
public static void createIndex() throws IOException {
IndexWriter writer = getIndexWriter();
try {
Document doc = new Document();
doc.add(new StringField("id", "1", Field.Store.YES)); //不分詞,索引,要存儲
doc.add(new TextField("name", "張三", Field.Store.YES)); //分詞,索引,存儲
doc.add(new IntField("age", 23, Field.Store.YES)); //不分詞,索引,存儲
doc.add(new StoredField("icon", "http://icon/****")); //不分詞,不索引,要存儲
doc.add(new TextField("introduction", "個人介紹", Field.Store.NO));//分詞,索引,不存儲
writer.addDocument(doc);
} finally {
writer.close();
}
}
//main方法中調用
public static void main(String[] args) throws IOException {
createIndex();
}
索引目錄中 產生了一些索引文件
term查詢文檔
//term查詢文檔
public static void query(String id) throws IOException {
//new TermQuery(new Term(SITE_ID, siteId.toString()))
IndexReader reader = DirectoryReader.open(getFSDirectory());
try {
IndexSearcher searcher = new IndexSearcher(reader);
Query query = new TermQuery(new Term("id", id));
//n代表查出前10條
TopDocs topDocs = searcher.search(query, 10);
System.out.println(">>>總記錄數" + topDocs.totalHits);
ScoreDoc[] docs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : docs) {
int docId = scoreDoc.doc; //文檔的id 跟存儲的id沒什么關系
Document doc = searcher.doc(docId);//獲取doc對象
System.out.println(doc.get("id"));
System.out.println(doc.get("name"));
System.out.println(doc.get("age"));
System.out.println(doc.get("icon"));
System.out.println(doc.get("introduction"));
}
} finally {
reader.close();
}
}
執行main函數
public static void main(String[] args) throws IOException {
// createIndex();
query("1");
}
輸出如下
可以看到introduction的輸出為null 這就是前面創建Field的時候 指定不存儲
>>>總記錄數1
1
張三
23
http://icon/****
null
term刪除
其實是根據查詢條件刪除
public static void delete(String id) throws IOException {
IndexWriter indexWriter = getIndexWriter();
try {
indexWriter.deleteDocuments(new Term("id", id));
// indexWriter.deleteAll(); 刪除所有文檔
} finally {
indexWriter.close(); //close的時候才會真正的刪除
}
}
main
public static void main(String[] args) throws IOException {
// createIndex();
delete("1");
query("1");
}
更新索引
public static void updateIndex(String id,String name) throws IOException {
IndexWriter writer = getIndexWriter();
try {
Document doc = new Document();
doc.add(new StringField("id", id, Field.Store.YES)); //不分詞,索引,要存儲
doc.add(new TextField("name", name, Field.Store.YES)); //分詞,索引,存儲
writer.updateDocument(new Term("id", id), doc);
} finally {
writer.close();
}
}
main函數
public static void main(String[] args) throws IOException {
createIndex();
// delete("1");
query("1");
updateIndex("1","李四");
query("1");
}
可以看到其實也是先刪除了 然后再添加
>>>總記錄數1
1
張三
23
http://icon/****
null
>>>總記錄數1
1
李四
null
null
null
BooleanQuery查詢文檔 并指定排序 懵B的 先記錄下來吧
public static void booleanQuery(String queryString) throws IOException {
//new TermQuery(new Term(SITE_ID, siteId.toString()))
IndexReader reader = DirectoryReader.open(getFSDirectory());
IndexSearcher searcher = new IndexSearcher(reader);
try {
BooleanQuery bq = new BooleanQuery();
Query q;
q = MultiFieldQueryParser.parse(queryString, new String[]{"name", "introduction"},
new BooleanClause.Occur[]{BooleanClause.Occur.SHOULD,
BooleanClause.Occur.SHOULD}, getAnalyzer());
bq.add(q, BooleanClause.Occur.MUST); //且
//查詢年齡 age>=1 && age <=30
q = NumericRangeQuery.newIntRange("age", 1, 30, true, true);
bq.add(q, BooleanClause.Occur.MUST); //且
Sort sort = new Sort();
List<SortField> sortFieldList = new ArrayList<SortField>();
//按照id從小到大
sortFieldList.add(new SortField("id", SortField.Type.STRING, false));
//并且 按照年齡從大到小
sortFieldList.add(new SortField("age", SortField.Type.INT, true));
sort.setSort(sortFieldList.toArray(new SortField[sortFieldList.size()]));
//n代表查出前10條
TopDocs topDocs = searcher.search(bq, 10, sort);
System.out.println(">>>總記錄數" + topDocs.totalHits);
ScoreDoc[] docs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : docs) {
int docId = scoreDoc.doc; //文檔的id 跟存儲的id沒什么關系
Document doc = searcher.doc(docId);//獲取doc對象
System.out.println(doc.get("id"));
System.out.println(doc.get("name"));
System.out.println(doc.get("age"));
System.out.println(doc.get("icon"));
System.out.println(doc.get("introduction"));
}
} catch (ParseException e) {
e.printStackTrace();
} finally {
reader.close();
}
}
自定義評分也記錄下
/**
* 重寫評分的實現方式
**/
private class MyScoreProvider extends CustomScoreProvider {
private AtomicReaderContext context;
public MyScoreProvider(AtomicReaderContext context) {
super(context);
this.context = context;
}
/**
* 重寫評分方法
**/
@Override
public float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {
// 從域緩存中加載索引字段信息
FieldCache.Ints ageInts = FieldCache.DEFAULT.getInts(context.reader(), "age", false);
int age = ageInts.get(doc);
//這里可以通過 一些 文檔Field的值 來為文檔打分 達到排序的效果
//doc實際上就是Lucene中得docId
float score = subQueryScore * valSrcScore; //分數
// 判斷加權
//....
/*
* 此處可以控制與原有得分結合的方式,加減乘除都可以
* **/
return score;
}
}
/**
* 重寫CustomScoreQuery 的getCustomScoreProvider方法
* 引用自定義的Provider
*/
private class MyCustomScoreQuery extends CustomScoreQuery {
public MyCustomScoreQuery(Query subQuery) {
super(subQuery);
}
@Override
protected CustomScoreProvider getCustomScoreProvider(AtomicReaderContext context) throws IOException {
/**注冊使用自定義的評分實現方式**/
return new MyScoreProvider(context);
}
}
查詢語句換一下 這里不能指定sort參數 sort參數優先級高
TopDocs docs = searcher.search(new MyCustomScoreQuery(query),10);