Используя Lucene к результатам подсчета в категориях

Невозможно найти обход по порядку, если дан только обход по порядку. Вот почему:

    A          A                              A
   /            \                            / \
  C              C                          B   C
 /                \
B                  B

Все имеют обход по порядку как: BCA

Но их обходы по порядку разные. BCA, ACB и BAC соответственно.

Вы должны иметь больше ограничений для уникального обхода обхода. Если такое ограничение состоит в том, что дерево завершено, то возможно иметь единственный обход по порядку.

18
задан 30 September 2008 в 07:46
поделиться

5 ответов

Вот то, что я сделал, хотя это немного тяжело на памяти:

то, В чем Вы нуждаетесь, должно создать заранее набор BitSet с, один для каждой категории, содержа идентификатор документа всех документов в категории. Теперь, на времени поиска Вы используете HitCollector и проверяете идентификаторы документа по BitSets.

Вот код для создания наборов битов:

public BitSet[] getBitSets(IndexSearcher indexSearcher, 
                           Category[] categories) {
    BitSet[] bitSets = new BitSet[categories.length];
    for(int i=0; i<categories.length; i++)
    {
        Query query = categories[i].getQuery();
        final BitSet bitset = new BitSet()
        indexSearcher.search(query, new HitCollector() {
            public void collect(int doc, float score) {
                bitSet.set(doc);
            }
        });
        bitSets[i] = bitSet;
    }
    return bitSets;
}

Это - всего один способ сделать это. Вы могли, вероятно, использовать TermDocs вместо того, чтобы запустить полный поиск, если Ваши категории достаточно просты, но это должно только работать однажды при загрузке индекса так или иначе.

Теперь, когда пора считать категории результатов поиска, Вы делаете это:

public int[] getCategroryCount(IndexSearcher indexSearcher, 
                               Query query, 
                               final BitSet[] bitSets) {
    final int[] count = new int[bitSets.length];
    indexSearcher.search(query, new HitCollector() {
        public void collect(int doc, float score) {
            for(int i=0; i<bitSets.length; i++) {
                if(bitSets[i].get(doc)) count[i]++;
            }
        }
    });
    return count;
}

то, С чем Вы заканчиваете, является массивом, содержащим количество каждой категории в результатах поиска. Если Вам также нужны результаты поиска, необходимо добавить TopDocCollector к коллектору хита (эй dawg...). Или, Вы могли просто запустить поиск снова. 2 поиска лучше, чем 30.

9
ответ дан 30 November 2019 в 08:53
поделиться

У меня нет достаточной репутации для комментария, но в ответе Матового Перепела я вполне уверен, Вы могли заменить это:

int numDocs = 0;
td.seek(terms);
while (td.next()) {
    numDocs++;
}

с этим:

int numDocs = terms.docFreq()

и затем избавляются от td переменной в целом. Это должно сделать его еще быстрее.

8
ответ дан 30 November 2019 в 08:53
поделиться

Таким образом позвольте мне видеть, понимаю ли я вопрос правильно: Учитывая запрос от пользователя, Вы хотите показать сколько соответствий, там для запроса в каждой категории. Корректный?

Думают о нем как это: Ваш запрос на самом деле originalQuery AND (category1 OR category2 or ...) за исключением хорошо общей оценки, Вы хотите получить число для каждой из категорий. К сожалению, интерфейс для сбора хитов в Lucene является очень узким, только давая Вам общую оценку для запроса. Но Вы могли реализовать пользовательский Маркер/Коллектор.

Взглянули на источник для org.apache.lucene.search. DisjunctionSumScorer. Вы могли скопировать часть этого для записи пользовательского маркера, который выполняет итерации через соответствия категории, в то время как основной поиск продолжается. И Вы могли оставаться Map<String,Long> для отслеживания соответствия в каждой категории.

0
ответ дан 30 November 2019 в 08:53
поделиться

Можно хотеть рассмотреть просмотр всех документов, которые соответствуют категориям с помощью итератор TermDocs .

Этот пример кода проходит каждый термин "Категории" и затем считает количество документов тем соответствием тот термин.

public static void countDocumentsInCategories(IndexReader reader) throws IOException {
    TermEnum terms = null;
    TermDocs td = null;


    try {
        terms = reader.terms(new Term("Category", ""));
        td = reader.termDocs();
        do {
            Term currentTerm = terms.term();

            if (!currentTerm.field().equals("Category")) {
                break;
            }

            int numDocs = 0;
            td.seek(terms);
            while (td.next()) {
                numDocs++;
            }

            System.out.println(currentTerm.field() + " : " + currentTerm.text() + " --> " + numDocs);
        } while (terms.next());
    } finally {
        if (td != null) td.close();
        if (terms != null) terms.close();
    }
}

Этот код должен работать довольно быстро даже за большими индексами.

Вот некоторый код, который тестирует тот метод:

public static void main(String[] args) throws Exception {
    RAMDirectory store = new RAMDirectory();

    IndexWriter w = new IndexWriter(store, new StandardAnalyzer());
    addDocument(w, 1, "Apple", "fruit", "computer");
    addDocument(w, 2, "Orange", "fruit", "colour");
    addDocument(w, 3, "Dell", "computer");
    addDocument(w, 4, "Cumquat", "fruit");
    w.close();

    IndexReader r = IndexReader.open(store);
    countDocumentsInCategories(r);
    r.close();
}

private static void addDocument(IndexWriter w, int id, String name, String... categories) throws IOException {
    Document d = new Document();
    d.add(new Field("ID", String.valueOf(id), Field.Store.YES, Field.Index.UN_TOKENIZED));
    d.add(new Field("Name", name, Field.Store.NO, Field.Index.UN_TOKENIZED));

    for (String category : categories) {
        d.add(new Field("Category", category, Field.Store.NO, Field.Index.UN_TOKENIZED));
    }

    w.addDocument(d);
}
2
ответ дан 30 November 2019 в 08:53
поделиться

Sachin, I believe you want faceted search. It does not come out of the box with Lucene. I suggest you try using SOLR, that has faceting as a major and convenient feature.

2
ответ дан 30 November 2019 в 08:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: