zoukankan      html  css  js  c++  java
  • [ lucene FAQ ] Lucene删除文档,使用IndexReader还是IndexWriter?

    lucene问题汇总:

    Lucene常见问题汇总

    从lucene API 可知,IndexReader和IndexWriter都具有删除指定文档的功能。

    IndexReader:

     void deleteDocument(int docNum)
              Deletes the document numbered docNum.
     int deleteDocuments(Term term)
              Deletes all documents that have a given term indexed.

    IndexWriter:

     void deleteDocuments(Query... queries)
              Deletes the document(s) matching any of the provided queries.
     void deleteDocuments(Query query)
              Deletes the document(s) matching the provided query.
     void deleteDocuments(Term... terms)
              Deletes the document(s) containing any of the terms.
     void deleteDocuments(Term term)
              Deletes the document(s) containing term.

    但是在实际应用中,我们删除文档到底是使用IndexReader还是IndexWriter呢?

    从IndexReader deleteDocuments方法可知:“Once a document is deleted it will not appear in TermDocs or TermPostitions enumerations.”

    即:reader进行删除后,此reader马上能够生效,而用writer删除后,会被缓存,只有写入到索引文件中,当reader再次打开的时候,才能够看到。

    实例演示:

    FSDirectory dir;
    IndexWriter w
    =null ;
    IndexSearcher sea
    =null ;
    try {
    dir
    = SimpleFSDirectory.open(new File("d:/realtime"));
    w
    =new IndexWriter(dir, null, MaxFieldLength.UNLIMITED ) ;
    sea
    =new IndexSearcher(dir);
    QueryParser parser
    =new QueryParser(Version.LUCENE_30, "f", new StandardAnalyzer(Version.LUCENE_30));
    String queryString
    ="fox6";
    Query query
    = parser.parse(queryString);
    TopDocs docs
    = sea.search(query, 1);
    ScoreDoc[] sd
    = docs.scoreDocs;
    for (int i =0; i < sd.length; i++) {
    System.out.println(
    "sea 1 :"+sea.doc(sd[i].doc));
    }
    //删除之前可以检索到
    //执行删除操作
    System.out.println("delete :"+ queryString );
    w.deleteDocuments(
    new Term("f", queryString));
    System.out.println(
    "delete finish ...");
    //删除之后可以检索到(说明indexWriter执行删除doc动作后不会立即生效)
    docs = sea.search(query, 1);
    sd
    = docs.scoreDocs;
    for (int i =0; i < sd.length; i++) {
    System.out.println(
    "sea 2 :"+sea.doc(sd[i].doc));
    }
    }
    catch (IOException e) {
    e.printStackTrace();
    }
    catch (ParseException e) {
    e.printStackTrace();
    }
    finally{
    if(w!=null){
    try {
    w.close();
    }
    catch (IOException e) {
    e.printStackTrace();
    }
    }
    if(sea!=null){
    try {
    sea.close();
    }
    catch (IOException e) {
    e.printStackTrace();
    }
    }

    }

    使用IndexWriter进行删除操作,删除后对删除的内容任然可以检索到,说明在当前IndexWriter实例当中删除的内容被缓存起来,并未马上生效!

    注意:

    即使IndexWriter在删除后进行提交(commit操作),也不会对删除动作马上生效。

    下面来看看IndexReader执行同样操作的情况:

    FSDirectory dir;
    IndexReader reader
    =null ;
    IndexSearcher sea
    =null ;
    try {
    dir
    = SimpleFSDirectory.open(new File("d:/realtime"));
    reader
    = IndexReader.open(dir,false);
    sea
    =new IndexSearcher(reader);
    QueryParser parser
    =new QueryParser(Version.LUCENE_30, "f", new StandardAnalyzer(Version.LUCENE_30));
    String queryString
    ="fox7";
    Query query
    = parser.parse(queryString);
    TopDocs docs
    = sea.search(query, 1);
    ScoreDoc[] sd
    = docs.scoreDocs;
    for (int i =0; i < sd.length; i++) {
    System.out.println(reader.document(sd[i].doc));
    }
    //删除之前可以检索到
    //执行删除操作
    System.out.println("delete :"+ queryString );
    reader.deleteDocuments(
    new Term("f", queryString));
    System.out.println(
    "delete finish ...");
    //删除之后检索不到(reader 对doc 删除后马上起效)
    docs = sea.search(query, 1);
    sd
    = docs.scoreDocs;
    for (int i =0; i < sd.length; i++) {
    System.out.println(reader.document(sd[i].doc));
    }
    }
    catch (IOException e) {
    e.printStackTrace();
    }
    catch (ParseException e) {
    e.printStackTrace();
    }
    finally{
    if(reader!=null){
    try {
    reader.close();
    }
    catch (IOException e) {
    e.printStackTrace();
    }
    }
    if(sea!=null){
    try {
    sea.close();
    }
    catch (IOException e) {
    e.printStackTrace();
    }
    }

    }

    IndexReader进行删除操作后,对删除的内容已不能检索,说明当前IndexReader实例已经对删除生效。

    从以上实例我们可以清楚了解IndexWriter和IndexReader在删除文档方面的不同之处,不过在此建议:

    在应用中使用IndexWriter进行删除操作!

    为什么呢?

    1.在实时索引当中,我们通常会对一份磁盘索引用IndexWriter打开,然后一份磁盘索引被IndexWriter打开后,IndexReader的删除操作将无法进行,否则会报LockObtainFailedException异常。

    2.Lucene的更新操作都是先删除后再添加的过程,如果使用IndexReader删除后,该动作马上生效,而添加动作又不会马上可见,会造成数据上的混乱(至少是理解上的混乱)。

    例如:用户更新文档A,用IndexReader先删除A文档,然后再添加修改过后的A文档,此时若添加的文档未被IndexSearcher重新打开,而用户对A文档进行检索发现检索不出A文档,此时将产生数据不一致。

  • 相关阅读:
    Postman初探
    web页面和本地数据对比问题
    Katalon Recorder初探
    Flask入门
    自我实现预言
    gulp 安装 依赖
    maven环境
    加解密 生成 X.509格式,DER编码,后缀名.cer。加密公钥证书
    我的魔法 公式找回中
    gulp 自动ftp至服务器时,处理开发 测试服务器地址问题
  • 原文地址:https://www.cnblogs.com/huangfox/p/1851031.html
Copyright © 2011-2022 走看看