`

Lucene学习总结之九:Lucene的查询对象(3)

阅读更多

6、FilteredQuery

FilteredQuery包含两个成员变量:

  • Query query:查询对象
  • Filter filter:其有一个函数DocIdSet getDocIdSet(IndexReader reader) 得到一个文档号集合,结果文档必须出自此文档集合,注此处的过滤器所包含的文档号并不是要过滤掉的文档号,而是过滤后需要的文档号。

FilterQuery所得到的结果集同两者取AND查询相同,只不过打分的时候,FilterQuery只考虑query的部分,不考虑filter的部分。

Filter包含很多种如下:

6.1、TermsFilter

其包含一个成员变量Set<Term> terms=new TreeSet<Term>(),所有包含terms集合中任一term的文档全部属于文档号集合。

其getDocIdSet函数如下:

  public DocIdSet getDocIdSet(IndexReader reader) throws IOException

  {

        //生成一个bitset,大小为索引中文档总数

        OpenBitSet result=new OpenBitSet(reader.maxDoc());

        TermDocs td = reader.termDocs();

        try

        {

            //遍历每个term的文档列表,将文档号都在bitset中置一,从而bitset包含了所有的文档号。

            for (Iterator<Term> iter = terms.iterator(); iter.hasNext();)

            {

                Term term = iter.next();

                td.seek(term);

                while (td.next())

                {

                    result.set(td.doc());

                }

            }

        }

        finally

        {

            td.close();

        }

        return result;

  }

 

6.2、BooleanFilter

其像BooleanQuery相似,包含should的filter,must的filter,not的filter,在getDocIdSet的时候,先将所有满足should的文档号集合之间取OR的关系,然后同not的文档号集合取NOT的关系,最后同must的文档号集合取AND的关系,得到最后的文档集合。

其getDocIdSet函数如下:

 

public DocIdSet getDocIdSet(IndexReader reader) throws IOException

{

  OpenBitSetDISI res = null;

  if (shouldFilters != null) {

    for (int i = 0; i < shouldFilters.size(); i++) {

      if (res == null) {

        res = new OpenBitSetDISI(getDISI(shouldFilters, i, reader), reader.maxDoc());

      } else {

        //将should的filter的文档号全部取OR至bitset中

        DocIdSet dis = shouldFilters.get(i).getDocIdSet(reader);

        if(dis instanceof OpenBitSet) {

          res.or((OpenBitSet) dis);

        } else {

          res.inPlaceOr(getDISI(shouldFilters, i, reader));

        }

      }

    }

  }

  if (notFilters!=null) {

    for (int i = 0; i < notFilters.size(); i++) {

      if (res == null) {

        res = new OpenBitSetDISI(getDISI(notFilters, i, reader), reader.maxDoc());

        res.flip(0, reader.maxDoc());

      } else {

        //将not的filter的文档号全部取NOT至bitset中

        DocIdSet dis = notFilters.get(i).getDocIdSet(reader);

        if(dis instanceof OpenBitSet) {

          res.andNot((OpenBitSet) dis);

        } else {

          res.inPlaceNot(getDISI(notFilters, i, reader));

        }

      }

    }

  }

  if (mustFilters!=null) {

    for (int i = 0; i < mustFilters.size(); i++) {

      if (res == null) {

        res = new OpenBitSetDISI(getDISI(mustFilters, i, reader), reader.maxDoc());

      } else {

        //将must的filter的文档号全部取AND至bitset中

        DocIdSet dis = mustFilters.get(i).getDocIdSet(reader);

        if(dis instanceof OpenBitSet) {

          res.and((OpenBitSet) dis);

        } else {

          res.inPlaceAnd(getDISI(mustFilters, i, reader));

        }

      }

    }

  }

  if (res !=null)

    return finalResult(res, reader.maxDoc());

  return DocIdSet.EMPTY_DOCIDSET;

}

6.3、DuplicateFilter

DuplicateFilter实现了如下的功能:

比如说我们有这样一批文档,每篇文档都分成多页,每篇文档都有一个id,然而每一页是按照单独的Document进行索引的,于是进行搜索的时候,当一篇文档的两页都包含关键词的时候,此文档id在结果集中出现两次,这是我们不想看到的,DuplicateFilter就是指定一个域如id,在此域相同的文档仅取其中一篇。

DuplicateFilter包含以下成员变量:

  • String fieldName:域的名称
  • int keepMode:KM_USE_FIRST_OCCURRENCE表示重复的文档取第一篇,KM_USE_LAST_OCCURRENCE表示重复的文档取最后一篇。
  • int processingMode:
    • PM_FULL_VALIDATION是首先将bitset中所有文档都设为false,当出现同组重复文章的第一篇的时候,将其设为1
    • PM_FAST_INVALIDATION是首先将bitset中所有文档都设为true,除了同组重复文章的第一篇,其他的的全部设为0
    • 两者在所有的文档都包含指定域的情况下,功能一样,只不过后者不用处理docFreq=1的文档,速度加快。
    • 然而当有的文档不包含指定域的时候,后者由于都设为true,则没有机会将其清零,因而会被允许返回,当然工程中应避免这种情况。

其getDocIdSet函数如下:

  public DocIdSet getDocIdSet(IndexReader reader) throws IOException

    {

        if(processingMode==PM_FAST_INVALIDATION)

        {

            return fastBits(reader);

        }

        else

        {

            return correctBits(reader);

        }

    }

  private OpenBitSet correctBits(IndexReader reader) throws IOException

    {

        OpenBitSet bits=new OpenBitSet(reader.maxDoc());

        Term startTerm=new Term(fieldName);

        TermEnum te = reader.terms(startTerm);

        if(te!=null)

        {

            Term currTerm=te.term();

           //如果属于指定的域

            while((currTerm!=null)&&(currTerm.field()==startTerm.field()))

            {

                int lastDoc=-1;

                //则取出包含此term的所有的文档

                TermDocs td = reader.termDocs(currTerm);

                if(td.next())

                {

                    if(keepMode==KM_USE_FIRST_OCCURRENCE)

                    {

                        //第一篇设为true

                        bits.set(td.doc());

                    }

                    else

                    {

                        do

                        {

                            lastDoc=td.doc();

                        }while(td.next());

                        bits.set(lastDoc); //最后一篇设为true

                    }

                }

                if(!te.next())

                {

                    break;

                }

                currTerm=te.term();

            }

        }

        return bits;

    }

private OpenBitSet fastBits(IndexReader reader) throws IOException

    {

        OpenBitSet bits=new OpenBitSet(reader.maxDoc());

        bits.set(0,reader.maxDoc());  //全部设为true

        Term startTerm=new Term(fieldName);

        TermEnum te = reader.terms(startTerm);

        if(te!=null)

        {

            Term currTerm=te.term();

            //如果属于指定的域

            while((currTerm!=null)&&(currTerm.field()==startTerm.field()))

            {

                if(te.docFreq()>1)

                {

                    int lastDoc=-1;

                    //取出所有的文档

                    TermDocs td = reader.termDocs(currTerm);

                    td.next();

                    if(keepMode==KM_USE_FIRST_OCCURRENCE)

                    {

                        //除了第一篇不清零

                        td.next();

                    }

                    do

                    {

                        lastDoc=td.doc();

                        bits.clear(lastDoc); //其他全部清零

                    }while(td.next());

                    if(keepMode==KM_USE_LAST_OCCURRENCE)

                    {

                        bits.set(lastDoc); //最后一篇设为true

                    }                   

                }

                if(!te.next())

                {

                    break;

                }

                currTerm=te.term();

            }

        }

        return bits;

    }

举例,我们索引如下的文件:

File indexDir = new File("TestDuplicateFilter/index");
IndexWriter writer = new IndexWriter(FSDirectory.open(indexDir), new StandardAnalyzer(Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED);
Document doc = new Document();
doc.add(new Field("id", "1", Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("contents", "page 1: hello world", Field.Store.YES, Field.Index.ANALYZED));
writer.addDocument(doc);

doc = new Document();
doc.add(new Field("id", "1", Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("contents", "page 2: hello world", Field.Store.YES, Field.Index.ANALYZED));
writer.addDocument(doc);

doc = new Document();
doc.add(new Field("id", "1", Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("contents", "page 3: hello world", Field.Store.YES, Field.Index.ANALYZED));
writer.addDocument(doc);

doc = new Document();
doc.add(new Field("id", "2", Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("contents", "page 1: hello world", Field.Store.YES, Field.Index.ANALYZED));
writer.addDocument(doc);

doc = new Document();
doc.add(new Field("id", "2", Field.Store.YES, Field.Index.NOT_ANALYZED));
doc.add(new Field("contents", "page 2: hello world", Field.Store.YES, Field.Index.ANALYZED));
writer.addDocument(doc);
writer.close();

如果搜索TermQuery tq = new TermQuery(new Term("contents","hello")),则结果为:

id : 1
id : 1
id : 1
id : 2
id : 2

如果按如下进行搜索:

File indexDir = new File("TestDuplicateFilter/index");
IndexReader reader = IndexReader.open(FSDirectory.open(indexDir));
IndexSearcher searcher = new IndexSearcher(reader);
TermQuery tq = new TermQuery(new Term("contents","hello"));
DuplicateFilter filter = new DuplicateFilter("id");
FilteredQuery query = new FilteredQuery(tq, filter);
TopDocs docs = searcher.search(query, 50);
for (ScoreDoc doc : docs.scoreDocs) {
  Document ldoc = reader.document(doc.doc);
  String id = ldoc.get("id");
  System.out.println("id : " + id);
}

则结果为:

id : 1
id : 2

 

6.4、FieldCacheRangeFilter<T>及FieldCacheTermsFilter

在介绍与FieldCache相关的Filter之前,先介绍FieldCache。

FieldCache缓存的是不是存储域的内容,而是索引域中term的内容,索引中的term是String的类型,然而可以将其他的类型作为String类型索引进去,例如"1","2.3"等,然后搜索的时候将这些信息取出来。

FieldCache支持如下类型:

  • byte[] getBytes (IndexReader reader, String field, ByteParser parser)
  • double[] getDoubles(IndexReader reader, String field, DoubleParser parser)
  • float[] getFloats (IndexReader reader, String field, FloatParser parser)
  • int[] getInts (IndexReader reader, String field, IntParser parser)
  • long[] getLongs(IndexReader reader, String field, LongParser parser)
  • short[] getShorts (IndexReader reader, String field, ShortParser parser)
  • String[] getStrings (IndexReader reader, String field)
  • StringIndex getStringIndex (IndexReader reader, String field)

其中StringIndex包含两个成员:

  • String[] lookup:按照字典顺序排列的所有term。
  • int[] order:其中位置表示文档号,order[i]第i篇文档包含的term在lookup中的位置。

FieldCache默认的实现FieldCacheImpl,其中包含成员变量Map<Class<?>,Cache> caches保存从类型到Cache的映射。

private synchronized void init() {

  caches = new HashMap<Class<?>,Cache>(7);

  caches.put(Byte.TYPE, new ByteCache(this));

  caches.put(Short.TYPE, new ShortCache(this));

  caches.put(Integer.TYPE, new IntCache(this));

  caches.put(Float.TYPE, new FloatCache(this));

  caches.put(Long.TYPE, new LongCache(this));

  caches.put(Double.TYPE, new DoubleCache(this));

  caches.put(String.class, new StringCache(this));

  caches.put(StringIndex.class, new StringIndexCache(this));

}

其实现接口getInts 如下,即先得到Integer类型所对应的IntCache然后,再从其中根据reader和由field和parser组成的Entry得到整型值。

public int[] getInts(IndexReader reader, String field, IntParser parser) throws IOException {

  return (int[]) caches.get(Integer.TYPE).get(reader, new Entry(field, parser));

}

各类缓存的父类Cache包含成员变量Map<Object, Map<Entry, Object>> readerCache,其中key是IndexReader,value是一个Map,此Map的key是Entry,也即是field,value是缓存的int[]的值。(也即在这个reader的这个field中有一个数组的int,每一项代表一篇文档)。

Cache的get函数如下:

 

public Object get(IndexReader reader, Entry key) throws IOException {

  Map<Entry,Object> innerCache;

  Object value;

  final Object readerKey = reader.getFieldCacheKey(); //此函数返回this,也即IndexReader本身

  synchronized (readerCache) {

    innerCache = readerCache.get(readerKey); //通过IndexReader得到Map

    if (innerCache == null) { //如果没有则新建一个Map

      innerCache = new HashMap<Entry,Object>();

      readerCache.put(readerKey, innerCache);

      value = null;

    } else {

      value = innerCache.get(key); //此Map的key是Entry,value即是缓存的值

    }

    //如果缓存不命中,则创建此值

    if (value == null) {

      value = new CreationPlaceholder();

      innerCache.put(key, value);

    }

  }

  if (value instanceof CreationPlaceholder) {

    synchronized (value) {

      CreationPlaceholder progress = (CreationPlaceholder) value;

      if (progress.value == null) {

        progress.value = createValue(reader, key); //调用此函数创建缓存值

        synchronized (readerCache) {

          innerCache.put(key, progress.value);

          }

        }

      }

      return progress.value;

  }

  return value;

}

Cache的createValue函数根据类型的不同而不同,我们仅分析IntCache和StringIndexCache的实现.

IntCache的createValue函数如下:

  protected Object createValue(IndexReader reader, Entry entryKey) throws IOException {

    Entry entry = entryKey;

    String field = entry.field;

    IntParser parser = (IntParser) entry.custom;

    int[] retArray = null;

    TermDocs termDocs = reader.termDocs();

    TermEnum termEnum = reader.terms (new Term (field));

    try {

      //依次将域中所有的term都取出来,用IntParser进行解析,缓存retArray[]位置即文档号,retArray[i]即第i篇文档所包含的int值.

      do {

        Term term = termEnum.term();

        if (term==null || term.field() != field) break;

        int termval = parser.parseInt(term.text());

        if (retArray == null)

          retArray = new int[reader.maxDoc()];

        termDocs.seek (termEnum);

        while (termDocs.next()) {

          retArray[termDocs.doc()] = termval;

        }

      } while (termEnum.next());

    } catch (StopFillCacheException stop) {

    } finally {

      termDocs.close();

      termEnum.close();

    }

    if (retArray == null)

      retArray = new int[reader.maxDoc()];

    return retArray;

  }

};

StringIndexCache的createValue函数如下:

protected Object createValue(IndexReader reader, Entry entryKey) throws IOException {

  String field = StringHelper.intern(entryKey.field);

  final int[] retArray = new int[reader.maxDoc()];

  String[] mterms = new String[reader.maxDoc()+1];

  TermDocs termDocs = reader.termDocs();

  TermEnum termEnum = reader.terms (new Term (field));

  int t = 0; 

  mterms[t++] = null;

  try {

    do {

      Term term = termEnum.term();

      if (term==null || term.field() != field) break;

      mterms[t] = term.text(); //mterms[i]保存的是按照字典顺序第i个term所对应的字符串。

      termDocs.seek (termEnum);

      while (termDocs.next()) {

        retArray[termDocs.doc()] = t; //retArray[i]保存的是第i篇文档所包含的字符串在mterms中的位置。

      }

      t++;

    } while (termEnum.next());

  } finally {

    termDocs.close();

    termEnum.close();

  }

  if (t == 0) {

    mterms = new String[1];

  } else if (t < mterms.length) {

    String[] terms = new String[t];

    System.arraycopy (mterms, 0, terms, 0, t);

    mterms = terms;

  }

  StringIndex value = new StringIndex (retArray, mterms);

  return value;

}

FieldCacheRangeFilter的可以是各种类型的Range,其中Int类型用下面的函数生成:

public static FieldCacheRangeFilter<Integer> newIntRange(String field, FieldCache.IntParser parser, Integer lowerVal, Integer upperVal, boolean includeLower, boolean includeUpper) {

  return new FieldCacheRangeFilter<Integer>(field, parser, lowerVal, upperVal, includeLower, includeUpper) {

    @Override

    public DocIdSet getDocIdSet(IndexReader reader) throws IOException {

      final int inclusiveLowerPoint, inclusiveUpperPoint;

      //计算左边界

      if (lowerVal != null) {

        int i = lowerVal.intValue();

        if (!includeLower && i == Integer.MAX_VALUE)

          return DocIdSet.EMPTY_DOCIDSET;

        inclusiveLowerPoint = includeLower ? i : (i + 1);

      } else {

        inclusiveLowerPoint = Integer.MIN_VALUE;

      }

      //计算右边界

      if (upperVal != null) {

        int i = upperVal.intValue();

        if (!includeUpper && i == Integer.MIN_VALUE)

          return DocIdSet.EMPTY_DOCIDSET;

        inclusiveUpperPoint = includeUpper ? i : (i - 1);

      } else {

        inclusiveUpperPoint = Integer.MAX_VALUE;

      }

      if (inclusiveLowerPoint > inclusiveUpperPoint)

        return DocIdSet.EMPTY_DOCIDSET;

      //从cache中取出values,values[i]表示第i篇文档在此域中的值

      final int[] values = FieldCache.DEFAULT.getInts(reader, field, (FieldCache.IntParser) parser);

      return new FieldCacheDocIdSet(reader, (inclusiveLowerPoint <= 0 && inclusiveUpperPoint >= 0)) {

        @Override

        boolean matchDoc(int doc) {

          //仅在文档i所对应的值在区间内的时候才返回。

          return values[doc] >= inclusiveLowerPoint && values[doc] <= inclusiveUpperPoint;

        }

      };

    }

  };

}

FieldCacheRangeFilter同NumericRangeFilter或者TermRangeFilter功能类似,只不过后两者取得docid的bitset都是从索引中取出,而前者是缓存了的,加快了速度。

同样FieldCacheTermsFilter同TermFilter功能类似,也是前者进行了缓存,加快了速度。

6.5、MultiTermQueryWrapperFilter<Q>

MultiTermQueryWrapperFilter包含成员变量Q query,其getDocIdSet得到满足此query的文档号bitset。

 

public DocIdSet getDocIdSet(IndexReader reader) throws IOException {

  final TermEnum enumerator = query.getEnum(reader);

  try {

    if (enumerator.term() == null)

      return DocIdSet.EMPTY_DOCIDSET;

    final OpenBitSet bitSet = new OpenBitSet(reader.maxDoc());

    final int[] docs = new int[32];

    final int[] freqs = new int[32];

    TermDocs termDocs = reader.termDocs();

    try {

      int termCount = 0;

      //遍历满足query的所有term

      do {

        Term term = enumerator.term();

        if (term == null)

          break;

        termCount++;

        termDocs.seek(term);

        while (true) {

          //得到每个term的文档号列表,放入bitset

          final int count = termDocs.read(docs, freqs);

          if (count != 0) {

            for(int i=0;i<count;i++) {

              bitSet.set(docs[i]);

            }

          } else {

            break;

          }

        }

      } while (enumerator.next());

      query.incTotalNumberOfTerms(termCount);

    } finally {

      termDocs.close();

    }

    return bitSet;

  } finally {

    enumerator.close();

  }

}

MultiTermQueryWrapperFilter有三个重要的子类:

  • NumericRangeFilter<T>:以NumericRangeQuery作为query
  • PrefixFilter:以PrefixQuery作为query
  • TermRangeFilter:以TermRangeQuery作为query

 

6.6、QueryWrapperFilter

其包含一个查询对象,getDocIdSet会获得所有满足此查询的文档号:

public DocIdSet getDocIdSet(final IndexReader reader) throws IOException {

  final Weight weight = query.weight(new IndexSearcher(reader));

  return new DocIdSet() {

    public DocIdSetIterator iterator() throws IOException {

      return weight.scorer(reader, true, false); //Scorer的next即返回一个个文档号。

    }

  };

}

 

 

6.7、SpanFilter

 

6.7.1、SpanQueryFilter 

其包含一个SpanQuery query,作为过滤器,其除了通过getDocIdSet得到文档号之外,bitSpans函数得到的SpanFilterResult还包含位置信息,可以用于在FilterQuery中起过滤作用。

public DocIdSet getDocIdSet(IndexReader reader) throws IOException {

  SpanFilterResult result = bitSpans(reader);

  return result.getDocIdSet();

}

 

public SpanFilterResult bitSpans(IndexReader reader) throws IOException {

  final OpenBitSet bits = new OpenBitSet(reader.maxDoc());

  Spans spans = query.getSpans(reader);

  List<SpanFilterResult.PositionInfo> tmp = new ArrayList<SpanFilterResult.PositionInfo>(20);

  int currentDoc = -1;

  SpanFilterResult.PositionInfo currentInfo = null;

  while (spans.next())

  {

    //将docid放入bitset

    int doc = spans.doc();

    bits.set(doc);

    if (currentDoc != doc)

    {

      currentInfo = new SpanFilterResult.PositionInfo(doc);

      tmp.add(currentInfo);

      currentDoc = doc;

    }

    //将start和end信息放入PositionInfo

    currentInfo.addPosition(spans.start(), spans.end());

  }

  return new SpanFilterResult(bits, tmp);

}

 

6.7.2、CachingSpanFilter

 

 

 

 

 

由Filter的接口DocIdSet getDocIdSet(IndexReader reader)得知,一个docid的bitset是同一个reader相对应的。

有前面对docid的描述可知,其仅对一个打开的reader有意义。

CachingSpanFilter有一个成员变量Map<IndexReader,SpanFilterResult> cache保存从reader到SpanFilterResult的映射,另一个成员变量SpanFilter filter用于缓存不命中的时候得到SpanFilterResult。

其getDocIdSet如下:

public DocIdSet getDocIdSet(IndexReader reader) throws IOException {

  SpanFilterResult result = getCachedResult(reader);

  return result != null ? result.getDocIdSet() : null;

}

private SpanFilterResult getCachedResult(IndexReader reader) throws IOException {

  lock.lock();

  try {

    if (cache == null) {

      cache = new WeakHashMap<IndexReader,SpanFilterResult>();

    }

    //如果缓存命中,则返回缓存中的结果。

    final SpanFilterResult cached = cache.get(reader);

    if (cached != null) return cached;

  } finally {

    lock.unlock();

  }

  //如果缓存不命中,则用SpanFilter直接从reader中得到结果。

  final SpanFilterResult result = filter.bitSpans(reader);

  lock.lock();

  try {

    //将新得到的结果放入缓存

    cache.put(reader, result);

  } finally {

    lock.unlock();

  }

  return result;


}

分享到:
评论

相关推荐

    Lucene学习源码.rar

    3. 执行查询:使用Query对象表示查询,然后通过Searcher执行查询。QueryParser可以自动分析查询字符串并生成Query对象。 4. 结果排序:Lucene提供了多种评分算法,如TF-IDF,用于衡量文档与查询的相关性,从而对...

    Lucene的的学习资料及案例

    3. **查询索引**: 创建一个IndexReader和IndexSearcher对象,然后构造Query对象,调用`search()`方法执行查询。 4. **处理结果**: `TopDocs`对象包含了搜索结果的分数和文档编号,可以进一步获取文档内容。 ### ...

    lucene学习资料收集

    4. **查询解析(Query Parsing)**:用户输入的查询字符串需要被解析成Lucene能理解的查询对象。这包括了查询分析、布尔操作符处理、短语查询等。 5. **搜索(Searching)**:通过查询对象,Lucene能高效地在索引中...

    Lucene5学习之分页查询

    本文将深入探讨"Lucene5学习之分页查询"这一主题,结合给定的标签"源码"和"工具",我们将讨论如何在Lucene5中实现高效的分页查询,并探讨其背后的源码实现。 首先,理解分页查询的重要性是必要的。在大型数据集的...

    lucene学习总结

    **Lucene学习总结** 在深入理解Lucene之前,我们首先需要了解什么是全文检索。全文检索是一种从大量文本数据中快速查找所需信息的技术。它通过建立索引来实现高效的搜索,而Lucene正是Java环境下最著名的全文搜索...

    Lucene 7.2.1 官方jar包

    - **QueryParser**: 解析用户输入的查询字符串,并转化为内部查询对象。 - **Searcher**: 执行查询,返回匹配文档的集合。 ### 3. Lucene的查询机制 - **布尔查询(Boolean Query)**: 支持AND、OR、NOT等逻辑...

    Lucene5学习之SpellCheck拼写纠错

    **标题:“Lucene5学习之SpellCheck拼写纠错”** 在深入探讨Lucene5的SpellCheck功能之前,首先需要理解Lucene是什么。Lucene是一个开源的全文检索库,由Apache软件基金会开发,它提供了高性能、可扩展的文本搜索...

    Lucene3.3.0学习Demo

    **Lucene 3.3.0 学习Demo** Lucene是一个开源的全文搜索引擎库,由Apache软件基金会开发。在3.3.0版本中,Lucene提供了强大的文本搜索功能,包括分词、索引创建、查询解析和结果排序等。这个"Lucene3.3.0学习Demo...

    lucene3源码分析

    ### Lucene3源码分析知识点概述 #### 一、全文检索的基本原理 ##### 1....以上是对Lucene3源码分析的一些关键知识点总结,通过对这些概念和技术的理解,可以更好地掌握Lucene的工作原理及其应用。

    Lucene3.0之查询类型详解

    【Lucene3.0查询类型详解】 在Lucene3.0中,查询处理是一个关键环节,涉及多种查询方式和理论模型。以下是对这些概念的详细解释: 1. **查询方式**: - **顺序查询**:是最简单的查询方式,直接遍历索引,效率较...

    Lucene搜索技术

    - **org.apache.lucene.queryParser**:解析查询字符串,生成可供搜索的查询对象。 - **org.apache.lucene.analysis**:包含语言分析器,用于文本预处理,例如英文分析模块,并支持自定义分析规则。 - **org.apache....

    lucene学习资料

    5. **搜索(Searching)**:通过查询对象,Lucene在索引中进行匹配,找出与之相关的文档。匹配度通过评分系统(Scoring)来衡量,通常基于TF-IDF(词频-逆文档频率)算法。 6. **高亮显示(Highlighting)**:为了...

    Lucene学习总结

    3. 添加字段:`Field`对象可以设置不同的属性,如是否存储原始内容(`Store.YES/NO`)、是否创建索引(`Index.ANALYZED/NOT_ANALYZED`)等。在示例中,可能创建了一个字段来存储《西游记》的文本,并设置为需要索引...

    lucene个人总结

    根据提供的文件信息,以下是对Lucene 3.5版本的核心知识点进行的详细解析与总结: ### Lucene 3.5 概述 Lucene 3.5 是一款高性能的全文检索引擎工具包,广泛应用于搜索引擎、文档管理和内容管理等领域。Lucene 的...

    lucene学习lucene学习

    用户输入的搜索词经过 `QueryParser` 分析后,生成一个查询对象,再通过 `IndexSearcher` 执行查询,返回匹配的文档列表。 总的来说,Lucene 提供了一套全面的文本处理工具,从文档解析到索引建立,再到高效搜索,...

    一步一步跟我学习lucene(12)---lucene搜索之分组处理group查询

    在"一步一步跟我学习lucene(12)---lucene搜索之分组处理group查询"中,我们将重点关注如何利用Lucene实现这一高级搜索功能。 首先,Lucene是一个开源全文搜索引擎库,它为Java开发者提供了构建高效、可扩展的搜索...

    Lucene原理及使用总结

    虽然Lucene不是数据库,但其数据结构和数据库有相似之处。索引可以看作是一种特殊的数据库,其中包含了对原始文档的引用和经过处理的关键词信息,便于快速查询。 【Lucene应用实例】 一个简单的Lucene应用实例是...

    Lucene 索引的简单使用

    本篇文章将详细阐述如何使用Lucene来创建和查询索引,帮助你深入理解其核心概念和操作流程。 ### 1. Lucene基本概念 - **文档(Document)**:在Lucene中,一个文档代表你要索引的信息单元,它可以包含多个字段...

    Lucene5学习之Highlighte关键字高亮

    《Lucene5学习之Highlighter关键字高亮》 在信息技术领域,搜索引擎的使用已经变得无处不在,而其中的关键技术之一就是如何有效地突出显示搜索结果中的关键字,这就是我们今天要探讨的主题——Lucene5中的...

Global site tag (gtag.js) - Google Analytics