Форум сайта python.su
Lexanderобъектов 1М, тегов 5К, кол-во фильтров, которое можно выбрать, не ограничено.
Решение, как обычно, зависит от используемых инструментов. Например, где хранить тэги.
Уточни, плз, объем обрабатываемых данных. А то миллион объектов…
Сколько объектов, сколько тэгов всего, сколько тэгов для каждого объекта, сколько тэгов можно одновременно выбрать из облака (кол-во фильтров)?..
Офлайн
на счет solr, желательно решение под питон и встраиваемое. а вообще охота сделать колесо, т.е. нужен алгоритм.
Офлайн
o7412369815963 Скажите, а в делали реальные измерение на миллионе записей?
Для базы данных это не так уж и много и обычная выборка здесь будет самое то.
Офлайн
o7412369815963Это условие похоже на сферического…
тегов 5К, кол-во фильтров, которое можно выбрать, не ограничено.
Офлайн
Lexanderвсе просто, на верх выходят часто используемые теги, где-нибуть штук 30, после того как 1 тег будет выбран он отсеет облако от которого из 5К останется 30, а если не видно, то можно воспользоваться поиском по тегам - автокомплит.
Ты себе представляешь страницу с 5к тэгов и пользователя, который тыкает на ВСЕ тэги? ;)
Офлайн
ZANпока не делал, но все равно пока вариантов нет. буду делать так.
o7412369815963 Скажите, а в делали реальные измерение на миллионе записей?
Для базы данных это не так уж и много и обычная выборка здесь будет самое то.
Офлайн
o7412369815963Попробовал потестить. Создал таблицу, где один столбец - данные, другой - тег:
пока не делал, но все равно пока вариантов нет. буду делать так.
/*create table*/
CREATE TABLE entry (
id SERIAL,
data varchar(32),
tag varchar(32)
);
import random
import hashlib
import psycopg2
CONN_STRING = "dbname=tags user=pmaster"
RECORDS = 1000000
TAGS = 1000
TAGS_FOR_RECORD = 5
def main():
tags = ['a', 'b', 'c', 'd', 'e']
progress = 0
record_list = []
for i in xrange(RECORDS/TAGS_FOR_RECORD):
#generating data to be saved
use_tags = random.sample(tags, 5)
data = hashlib.md5(str(i)).hexdigest()
record_list.append([data, use_tags])
#splitting data into portions
if i % (RECORDS/(TAGS_FOR_RECORD*TAGS)) == 0:
#printing progress
progress += 1
print progress
save_records(record_list)
record_list = []
#adding new tags
tags.append('tag%s' %i)
save_records(record_list)
print '---'
print 'records:', (i+1)*TAGS_FOR_RECORD, 'tags:', len(tags)
def save_records(record_list):
conn = psycopg2.connect(CONN_STRING)
cur = conn.cursor()
for data, tags in record_list:
for tag in tags:
cur.execute('insert into entry (data, tag) values (%s, %s)', (data, tag))
conn.commit()
cur.close()
conn.close()
/* get tag cloud of most popular tags*/
select
count(tag), tag
from
entry
group by
tag
order by
count(tag) desc fetch first 100 rows only
/* 0.39 s */
select
count(tag), tag
from
entry
where (data in (
select
data
from
entry
where
tag='d'))
and (tag!= 'd')
group by
tag
order by
count(tag) desc
fetch first 100 rows only
/* 0.79 s */
select distinct
data
from
entry
where
(tag = 'b') and data in (
select
data
from
entry
where
tag = 'c')
fetch first 100 rows only
/* 0.25 s */
Офлайн
в данном примере кол-во объектов 200К а не миллион (RECORDS/TAGS_FOR_RECORD).
запрос сужения мне кажется не оптимальным - на каждый фильтрующий тег - вложенный запрос, т.е. от 5-и тегов база здохнет.
у меня все это крутиться на mongoDB, попробую сделать выборку одним проходом (без вложенных запросов)
Отредактировано (Сен. 17, 2010 17:33:35)
Офлайн
o7412369815963Ну да, это только для примерной оценки сложности запроса. Просто задача сужения позволяет делать последующую выборку по уже полученным результатам (хранить курсор или временные таблицы), которая будет проходить наобарот быстрее предыдущей, и удалять кеш после завершения сессии пользователя или по какому-нибудь явному вызову invalidate.
запрос сужения мне кажется не оптимальным - на каждый фильтрующий тег - вложенный запрос, т.е. от 5-и тегов база здохнет.
Офлайн
o7412369815963Ты бы сразу уточнил об используемых инструментах.
запрос сужения мне кажется не оптимальным - на каждый фильтрующий тег - вложенный запрос, т.е. от 5-и тегов база здохнет.
у меня все это крутиться на mongoDB, попробую сделать выборку одним проходом (без вложенных запросов)
db.entry.find({tag: {$all: ['c', 'd']}})
Офлайн