Уведомления

Группа в Telegram: @pythonsu

#1 Сен. 18, 2010 20:16:31

Lexander
От:
Зарегистрирован: 2008-09-19
Сообщения: 1139
Репутация: +  33  -
Профиль   Отправить e-mail  

теги

Небольшой пример на основании приведенной таблицы элементов для того, чтобы убедиться - мы имеем в виду одно и то же.
1. Выводим первые Х тегов.
2. Выбираем тэг В — в выборке остаются элементы 1, 2, 4, 10. В облаке остаются тэги А, В, С, D, F. Что еще нужно вывести, количество каждого тэга в полученном списке элементов: А = 1, B = 4, C = 2, D = 1, F = 1, так? Еще что-то?
3. Выбираем второй тэг C — в выборке 2 элемента: 1 и 2. В облаке остаются тэги: A, B, C, D. Аналогично п.2 А = 1, B = 2, C = 2, D = 1. Дополнительно выводим то, что было задумано в п.2.
4. Выбираем третий тэг А — в выборке элемент 1. В облаке: A, B, C. Все тэги имеют значение 1.

Так?
Если еще что-то нужно выводить, покажи на этом примере что выводится и какое значение должно иметь, исходя из приведенных данных.



Офлайн

#2 Сен. 18, 2010 21:33:02

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

теги

o7412369815963
это и есть простой граф который я выложил выше в посте 35, из него не получить фильтр по 2-м тегам
Да, согласен. Без списка id объектов, оттеженых каждым тэгом не получить.
Но с ним вроде как не должно быть проблем. посмотрим на примере:
{tag1: ,
tag2: ,
tag3: ,
tag4: }
Итого на первом уровне показываем просто все тэги и длины их списков id:
tag1(5), tag2(4), tag3(5), tag4(2)
На втором уровне для скажем tag1 легко получим: tag2(3) tag3(3) и tag4(1)
На третьем для tag2 получим tag3(2) и tag4(1)

Ну и так далее. Все находится простым пересечением множеств. Того же redis-а тут должно хватить за глаза. Или проблема в том, что хранить оба соответствия объект - тэг и тэг - объект не хочется?



Офлайн

#3 Сен. 18, 2010 21:51:50

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

теги

мдя, map_reduce можно же на find накладывать… тогда должно быстрее гораздо работать, ща проверю :)

Lexander
Так?
Если еще что-то нужно выводить, покажи на этом примере что выводится и какое значение должно иметь, исходя из приведенных данных.
да, так… надо будет проверить производительность :)

Офлайн

#4 Сен. 18, 2010 21:59:35

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

теги

Ed
Ну и так далее. Все находится простым пересечением множеств. Того же redis-а тут должно хватить за глаза. Или проблема в том, что хранить оба соответствия объект - тэг и тэг - объект не хочется?
идея не плохая, но тегов 5К.

Офлайн

#5 Сен. 18, 2010 22:11:20

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

теги

o7412369815963
мдя, map_reduce можно же на find накладывать… тогда должно быстрее гораздо работать, ща проверю :)
сделал так:
    tags = db.events.map_reduce(map, reduce, query={ 'tags': { '$all': [ 'a', 'b' ] } })
tags = list(tags.find().sort('value',DESCENDING).limit(100))
200К обрабатывает за 3сек, элементов попавших под условие (2 тега) = 65000

ща сделаю разнообразие тегов поболее, т.е. приближу к реальности, должно ещё шустрее обрабатываться

Офлайн

#6 Сен. 18, 2010 22:11:35

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

теги

То, что тэгов 5K еще полбеды. Оттеженых одним тэгом объектов может быть потенциально 1M, а это хуже.
Но redis такое вроде как умеет. Вот из его FAQ:
Q: What is the maximum number of keys a single Redis instance can hold? and what the max number of elements in a List, Set, Ordered Set?¶

A: In theory Redis can handle up to 2^32 keys, and was tested in practice to handle at least 150 million of keys per instance. We are working in order to experiment with larger values.

Every list, set, and ordered set, can hold 2^32 elements.

Actually Redis internals are ready to allow up to 2^64 elements but the current disk dump format don't support this, and there is a lot time to fix this issues in the future as currently even with 128 GB of RAM it's impossible to reach 2^32 elements.



Отредактировано (Сен. 18, 2010 22:12:00)

Офлайн

#7 Сен. 18, 2010 22:32:12

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

теги

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

o7412369815963
ща сделаю разнообразие тегов поболее, т.е. приближу к реальности, должно ещё шустрее обрабатываться
итого: объектов 200К, тегов 500, на каждый объект по 5 тегов
1) выборка 100 отсортированных элементов: 0.031 s
2) выборка 100 отсортированных тегов: 0.076 s

увеличение числа фильтров (кол-ва тегов) не увеличивает затрачиваемое время!!!

в дальнейшем для увеличения производительности, теги заменю индексами (теги в отдельную коллекцию)

сейчас протестирую на 1М объектов, 5К тегов, 10 тегов на элемент

Офлайн

#8 Сен. 18, 2010 23:11:12

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

теги

o7412369815963
сейчас протестирую на 1М объектов, 5К тегов, 10 тегов на элемент
результат:
1) выборка 100 отсортированных элементов: 0.049 s
2) выборка 100 отсортированных тегов: 0.122 s

монга рулит :)
всем спасибо!

Отредактировано (Сен. 18, 2010 23:14:08)

Офлайн

#9 Сен. 20, 2010 13:18:37

ZAN
От:
Зарегистрирован: 2007-06-10
Сообщения: 403
Репутация: +  10  -
Профиль   Отправить e-mail  

теги

Выложи плиз решение, интересно очень )



Офлайн

#10 Сен. 21, 2010 05:29:32

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

теги

это добавление тегов в граф (старый список тегов и новый для одного объекта)

def EventTags_set(t_old1,t_new1):
#r = []
#for t in t_old:
# if t in t_new: r.append(t)
#for t in r:
# del t_old[t]
# del t_new[t]
#raise Exception(str( t_new ))
t_old = []
for t in t_old1:
if t not in t_new1: t_old.append(t)
t_new = []
for t in t_new1:
if t not in t_old1: t_new.append(t)

# remove
db = getDBn()
for name in t_old:
tag = db.events_tags.find_one({ 'name':name })
if not tag: continue
tag['count'] -= 1
tags = tag['tags']
for n in t_old:
if name != n:
if n in tags:
if tags[n] < 2: del tags[n]
else: tags[n] -= 1
db.events_tags.save(tag)
# append
for name in t_new:
tag = db.events_tags.find_one({ 'name':name })
if not tag: tag = { 'name':name, 'tags':{}, 'count':0 }
tag['count'] += 1
tags = tag['tags']
for n in t_new:
if name != n:
if n in tags: tags[n] += 1
else: tags[n] = 1
db.events_tags.save(tag)
Получение тегов
def EvenetTags_list(tags):
db = getDBn()

if not len(tags): return db.events_tags.find({},{ 'name':1, 'count':1 }).sort('count',DESCENDING)
elif len(tags) == 1:
tt = db.events_tags.find_one({ 'name':tags[0] })
if not tt: return []
tt = tt['tags']
return sorted( [ { 'name':t, 'count':tt[t]} for t in tt ] , key=lambda x:x['count'], reverse=True )

map = Code(""" function() {
this.tags.forEach(
function(x) {
emit(x, 1);
}
);
}""")

reduce = Code("""function (key, values) {
var total = 0;
for(var i in values) total += values[i];
return total;
}""")

result = db.events.map_reduce(map, reduce, query={ 'tags': { '$all': tags } })
result = list(result.find().sort('value',DESCENDING).limit(100))
return [ { 'name':x['_id'], 'count':x['value'] } for x in result if x['_id'] not in tags ]
без фильтра или с 1 фильтром - берет из графа, если 2 и более - мап_редьюс

Отредактировано (Сен. 21, 2010 05:33:30)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version