Ищете более быстрый алгоритм для подсчета тегов/ключевых слов/меток в базе данных документов для динамического облака тегов.

Текущее состояние

  • Приложение .NET 4.0 (WPF)
  • База данных: SQLCE
  • Таблицы (упрощенно): Документы, Теги, ДокументыТеги [n:n]
  • примерно 2000 документов и 600 тегов (теги могут быть назначены нескольким документам)
  • теги = ключевые слова = ярлыки

Дело

У пользователя есть большая база данных документов, которую он может фильтровать с помощью облака тегов. Теги отображают имя (само имя тега) и число, которое представляет собой общее количество документов с соответствующим тегом. Если пользователь выбирает тег, отображаются только документы с выбранным тегом. Облако динамических тегов теперь должно отображать только доступные теги в отфильтрованных документах с обновленным номером счетчика.

Проблема

Это медленно. После каждого выбранного тега нам нужно снова оценить все документы, чтобы подсчитать теги. Сейчас мы делаем это рекурсивно, поэтому проверяем каждый документ, какие у него теги. Ищем другое решение (кеширование, лучший алгоритм, ваша идея?).

Сходства

stackoverflow, del.icio.us также имеют облака тегов. Проверьте себя. Как они это делают? Я знаю, что хранимые процедуры были бы решением, но, по словам нашего разработчика базы данных, они недоступны в SQLCE.


person Wolkenjaeger    schedule 15.02.2012    source источник
comment
Правильно ли я понимаю, что медленная часть отображает теги только для списка документов, выделенных одним тегом?   -  person Eugen Rieck    schedule 15.02.2012
comment
Что ж, на самом деле, чем меньше документов отображается, тем быстрее это происходит, поскольку мы получаем теги каждый раз, когда список фильтруется. Теперь при запуске приложения доступны все 2000 документов, и наше приложение получает все теги документ за документом.   -  person Wolkenjaeger    schedule 15.02.2012
comment
Мой ответ ниже помогает в этом! Не нужно циклически перебирать документы, это можно сделать одним запросом.   -  person Eugen Rieck    schedule 15.02.2012


Ответы (2)


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

Один инвертированный индекс на самом деле будет map:Tags->list of Tags [все теги, которые совпадают с ключом]
Второй будет map:Tags->list of Docs [все документы, которые совпадают с каждым тегом].

Вычисление соответствующего набора документов после выбора некоторых тегов — это просто пересечение инвертированного индекса, что можно сделать эффективно.
Кроме того, обнаружение измененного облака тегов снова является пересечением инвертированного индекса.

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

Эта тема обсудить, как эффективно находить пересечение в инвертированном индексе

person amit    schedule 15.02.2012
comment
Это кажется очень многообещающим. Мы должны изучить это решение, что займет некоторое время. Спасибо за ваш вклад! - person Wolkenjaeger; 15.02.2012

Вам следует выполнить второй этап поиска в одном запросе, например

SELECT
  tags.id AS tagid,
  tags.name AS tagname,
  count(*) AS tagcount
FROM
  tags
  INNER JOIN DocumentsTags AS tda on tda.tagid=tags.id
  INNER JOIN DocumentsTags AS tdb on tda.documentid=tdb.documentid
WHERE
  tdb.tagid=<selected tag id>
GROUP BY
  tags.id

Изменить

После вашего комментария это то, что вы должны использовать для запроса первого этапа (т. е. тег еще не выбран, все документы в списке)

SELECT
  tags.id AS tagid,
  tags.name AS tagname,
  count(*) AS tagcount
FROM
  tags
  INNER JOIN DocumentsTags AS tda on tda.tagid=tags.id
GROUP BY
  tags.id
person Eugen Rieck    schedule 15.02.2012