Lucene:如何在进行分组搜索时按组中的文档计数进行排序

时间:2013-09-05 02:01:24

标签: java lucene

我有像

这样的文件
{id:1, name:foo, from: China}
{id:2, name:bar, from: USA}
{id:3, name:baz, from: Japan}
{id:4, name:foo, from: China}

然后我按from字段对这些文档进行分组。

  

我希望获得用户来自的前N个国家。

我不知道如何按每个组的文档计数排序。 或者有更好的方法来做到这一点。

3 个答案:

答案 0 :(得分:0)

也许你可以sort这样new Sort(new SortField[]{new SortField("from", SortField.STRING), new SortField("id", SortField.INT)})

如果您有其他要求,可以实现自己的Collector,Lucene将使用最小堆收集结果,并且您可以使用存储具有相同from的doc的树集堆中的元素,在树集中,您可以按id排序。

答案 1 :(得分:0)

我不认为使用Lucene是实现目标的最佳方式,但您可以迭代结果并在地图中收集每个国家/地区的数量:

final Map<String, Integer> country2count = new HashMap<String, Integer>();
    for (final ScoreDoc hit : hits) {
        final int docId = hit.doc;
        if (!reader.isDeleted(docId)) {
            // Get the document from docId
            final Document document = searcher.doc(docId);
            // Get the country
            final String country = document.get("from");

            if(country2count.containsKey(country)){
                int prevCount = country2count.get(country);
                country2count.put(country, ++prevCount);
            }else{
                country2count.put(country, 1);
            }
        }
    }

我建议您不要使用索引而是使用简单的日志,而不是使用具有最多用户数的国家/地区:

cat id_name_from.log | awk'{print $ 3}'| sort -k 3 | uniq -c | sort -nrk 1

实施例: 日志文件保存为“id \ t name \ t from”:

1   foo China
2   foo Usa
3   bar China
4   foo China
5   foo China
6   foo Usa
7   bar China
8   foo China
9   foo Usa

脚本:

cat log | awk '{print $3}' | sort | uniq -c | sort -nrk 1

结果:

6 China
3 Usa

答案 2 :(得分:0)

// Do a first pass (this is the "expensive" part)
String gField = "from";
Sort gSort = Sort.RELEVANCE;
int gOffset = 0;
int gLimit = 25;
TermFirstPassGroupingCollector firstCollector = new TermFirstPassGroupingCollector(...);
indexSearcher.search(query, firstCollector);
Collection<SearchGroup<BytesRef>> topGroups = firstCollector.getTopGroups(...);

//Do a second pass
Sort sortWithinGroup = new Sort(new SortField("WhateverYouWantToSortBy"...));
int offsetInGroup = 0;
int docsPerGroup = 1;
TermSecondPassGroupingCollector secondCollector = new TermSecondPassGroupingCollector(...);
indexSearcher.search(query, secondCollector);
TopGroups<BytesRef> results = secondCollector.getTopGroups(offsetInGroup);

// Do other stuff ...