欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Lucene字段

程序员文章站 2022-07-09 10:26:05
...

Lucene中字段类型主要有以下几种:

1.TextField:

	TextField会把改字段的内容索引并词条化,但是不保存词向量。比如:包含正片文档内容的body字段,常常使用
TextField类型进行索引

2.StringField:

	StringField只会对该字段的内容索引,但是并不词条化,也不保存词向量。字符串的值会被索引为一个单独的词项
比如:国家的名称字段,字段名为"country" ,以国家『阿尔及利亚』为例,只索引不词条化时最合理的。

3.IntPoint

	IntPoint适合索引值为int类型的字段。IntPoint时为了快速过滤的,如果需要展示出来需要另存一个字段。比如
商品的数量用字段"productCOunt"存储,根据商品数量进行过滤操作时可以直接通过productCount字段获取结果,
但是要想展示商品数量,需要另外再存储一个字段。

4.LongPoint

	用法跟IntPoint类似,区别在LongPoint适合索引值为长整形long类型的字段。

5.FloatPoint

	用法和IntPoint类似,区别在DoublePoint适合索引值为double类型的字段。

6.SortedDocValuesField

	存储值为文本内容的DocValue字段,SortedDocValuesField适合索引字段值为文本内容并且需要按值进行排序的
字段

7.SortedSetDocValuesField

	存储多值域的DocValues字段,SortedSetDocValuesField 适合索引字段值为文本内容且需要按值进行分组,
聚合等操作的字段。

8.NumericDocValuesField

	存储单个数值类型的DocValues字段。主要包括(int,long,float,double)

9.SortedNumericDocValuesField

	存储数值类型的有序数组列表的DocValues字段

10.StoredField

	StoredField适合索引只需要保存字段值不进行其他操作的字段
Lucene索引文档要依靠一个IndexWriter对象,创建IndexWriter需要提供两个参数,一个是IndexWriterConfig
对象,带对象可以设置创建索引使用哪种分词器,另一个是索引的保存路径。

Lucene————> IndexWriter————> 1.IndexWriterConfig,2,索引保存路径

IndexWriter 对象的addDocument()方法用于添加文档,该方法的参数为Document对象,
IndexWriter 对象一次可以添加多个文档,最后调用commit()方法生成索引。

Document类表示文档,比文档更小的单位是域,也可以称为字段,一个文档可以有多个域。FieldType对象用于指定域的
的索引信息,例如是否解析,是否存储,是否保存词项频率,位移信息等。FieldType对象的setIndexOptions()方法
可以设定域的索引选项。可选参数以及含义如下:

1.IndexOptions.DOCS
只索引文档,词项频率和位移信息不保存

2.IndexOptions.DOC_AND_FREQS
只索引文档和词项频率,位移信息不保存

3.IndexOptions.DOC_AND_FREQS_AND_POSITIONS
索引文档,词频信息和位移信息

4.IndexOptions.DOC_AND_FREQS_AND_POSITIONS_AND_OFFSETS
索引文档,词项频率,位移信息和偏移量

5.IndexOptions.NONE
不索引

全文搜索中很重要的一项需求是关键字的高亮,要想准确的获取位置信息以及一些偏移量就需要在创建索引的时候进行记录
,如果信息不准确,那么可能在搜索的时候就会发生错位,反映到网页上就是标注了不该标注的字,没有标注该标的内容,
在索引的时候,可以使用FieldType对象提供的方法设置相对增量和位移信息。

1.setSorted(boolean value)
参数默认值为false,设置为true存储字段值

2.setTokenized(boolean value)
参数设置为true,会使用配置的分词器对字段值进行词条化

3.setStoreTermVectors(boolean value)
参数为true,保存词向量

4.setStoreTermVectorPositions(boolean value)
参数为true,保存词向量中的位移信息

5.setStoreTermVectorOffsets(boolean value)
参数为true,保存词项在向量中的偏移信息。

*** 实例代码如下:创建索引 ***

package tup.lucene.index;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import tup.lucene.ik.IKAnalyzer6x;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;


/**
 * @Project_Name: nowayplatform
 * @Author: WeiS
 * @Description: 创建索引
 * @Date: 2019-05-15 23:09
 */
public class CreateIndex {


    public static void main(String[] args) {
        //创建3个news对象
        News news1 = new News();
        news1.setId(1);
        news1.setTitle("*回见美国总统奥巴马,学习国外经验");
        news1.setContent("国家主席*9月3日在杭州西湖国宾馆回见前来出席二十国集团*杭州峰会的美国总统奥巴马。。。");
        news1.setReply(672);


        News news2 = new News();
        news2.setId(2);
        news2.setTitle("北大迎 4380名新生 农村学生700多人近年最多");
        news2.setContent("昨天,北京大学迎来4380名来自全国各地及数十个国家的本科新生。其中,农村学生共700余名,为近年最多。。。");
        news2.setReply(995);

        News news3 = new News();
        news3.setId(3);
        news3.setTitle("特朗普宣誓 (Donald Trump)就任美国第45任总统");
        news3.setContent("当地时间1月20日,唐纳德.特朗普在美国国会宣誓就职,正式成为美国第45任总统。");
        news3.setReply(1872);

        //创办IK 分词器
        Analyzer analyzer = new IKAnalyzer6x();
        IndexWriterConfig icw = new IndexWriterConfig(analyzer);
        //OpenMode.CREATE 参数表示 先清空索引再重新创建,传入CREATE_OR_APPEND参数表示如果索引不存在会新建,已存在
        //会附加
        icw.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
        // 用于表示索引的位置
        Directory dir;
        IndexWriter indexWriter ;
        //索引目录
        Path indexPath = Paths.get("indexdir");

        //开始时间
        Date start =new Date();

        System.out.println("start-------------------"+start.getTime());

        try {
            if (!Files.isReadable(indexPath)) {
                System.out.println("Document directory"+indexPath.toAbsolutePath()+"does not exist or is" +
                        "not readable, please check the path");
                System.exit(1);
            }

            dir  = FSDirectory.open(indexPath);
            indexWriter = new IndexWriter(dir,icw);
            //设置新闻id索引并存储
            FieldType idtype = new FieldType();
            idtype.setIndexOptions(IndexOptions.DOCS);
            idtype.setStored(true);
            //设置新闻标题索引文档,词项频率,位移信息和偏移量,存储并词条化
            FieldType titleType = new FieldType();
            titleType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
            titleType.setStored(true);
            titleType.setTokenized(true);

            FieldType contentType = new FieldType();
            contentType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
            contentType.setStored(true);
            contentType.setTokenized(true);
            contentType.setStoreTermVectors(true);
            contentType.setStoreTermVectorPositions(true);
            contentType.setStoreTermVectorOffsets(true);
            contentType.setStoreTermVectorPayloads(true);

            Document doc1 = getDoc(news1,idtype,titleType,contentType);
            Document doc2 = getDoc(news2,idtype,titleType,contentType);
            Document doc3 = getDoc(news3,idtype,titleType,contentType);

            indexWriter.addDocument(doc1);
            indexWriter.addDocument(doc2);
            indexWriter.addDocument(doc3);

            indexWriter.commit();
            indexWriter.close();
            dir.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

        Date end = new Date();
        System.out.println("end-------------------"+end.getTime());
        System.out.println("索引文档用时:"+(end.getTime()-start.getTime())/1000+"秒");

    }

    private static Document getDoc(News news, FieldType idtype, FieldType titleType, FieldType contentType) {
        Document doc = new Document();
        doc.add(new Field("id",String.valueOf(news.getId()),idtype));
        doc.add(new Field("title",String.valueOf(news.getTitle()),titleType));
        doc.add(new Field("content",String.valueOf(news.getContent()),contentType));
        doc.add(new IntPoint("reply",news.getReply()));
        doc.add(new StoredField("reply_display", news.getReply()));
        return doc;
    }
}


输出结果:

start-------------------1557936588057
加载扩展词典:ext.dic
加载扩展停止词典:stopword.dic
加载扩展停止词典:ext_stopword.dic
end-------------------1557936589036
索引文档用时:0秒

*** 实例代码如下:删除索引 ***

package tup.lucene.index;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;
import tup.lucene.ik.IKAnalyzer6x;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * @Project_Name: nowayplatform
 * @Author: WeiS
 * @Description: 删除索引
 * @Date: 2019-05-16 21:48
 */
public class DeleteIndex {

    public static void main(String[] args) {
        //删除title中含有关键词 『美国』 的文档
        deleteDoc("title","美国");
    }

    private static void deleteDoc(String title, String name) {
        Analyzer analyzer = new IKAnalyzer6x();
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
        Path path = Paths.get("indexdir");
        Directory directory;
        try{
            directory = FSDirectory.open(path);
            IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);
            indexWriter.deleteDocuments(new Term(title,name));
            indexWriter.commit();
            indexWriter.close();
            System.out.println("删除完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


*** 除此之外,IndexWriter还提供了以下方法:***

1.DeleteDocuments(Query query) 根据Query条件删除单个或多个Document
2.DeleteDocuments(Query[] queries) 根据Query条件来删除单个或多个Document
3.DeleteDocuments(Term term) 根据Term来删除单个或多个Document
4.DeleteDocuments(Term[] term) 根据Term来删除单个或多个Document
5.DeleteAll() 删除所有的Document

使用IndexWriter 进行Document删除时,文档并不会立即被删除,而是把这个删除动作缓存起来,当
IndexWriter.Commit() 或 IndexWriter.Close()时,删除操作才会被真正执行。

*** 索引的更新 ***
索引更新操作实质上是先删除索引,再重新建立新的文档

package tup.lucene.index;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import tup.lucene.ik.IKAnalyzer6x;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * @Project_Name: nowayplatform
 * @Author: WeiS
 * @Description: 更新索引
 * @Date: 2019-05-16 22:05
 */
public class UpdateIndex {


    public static void main(String[] args) {
        Analyzer analyzer = new IKAnalyzer6x();
        IndexWriterConfig iwc = new IndexWriterConfig(analyzer);
        Path index = Paths.get("indexdir");
        Directory directory;
            try {
                directory = FSDirectory.open(index);
                IndexWriter indexWriter = new IndexWriter(directory,iwc);
                Document doc = new Document();

                doc.add(new TextField("id","2", Field.Store.YES));
                doc.add(new TextField("title","北京大学开学迎来4380名新生", Field.Store.YES));
                doc.add(new TextField("content","昨天,北京大学迎来4380名来自全国各地数十个国家的
                本科新生。其中农村学生共有" +
                        "700余名,为近年最多。。。", Field.Store.YES));
                indexWriter.updateDocument(new Term("title","北大"),doc);
                indexWriter.commit();
                indexWriter.close();

            } catch (IOException e) {

                e.printStackTrace();
        }
    }
}

上面的代码中新建了一个IndexWriter对象和Document对象,通过updateDocument() 方法完成更新操作。Term
对象用于定位文档,查找title中含有『北大』的文档,然后用新的文档替换原文档,这样就完成了更新操作。