parserALT
Страницы форума: ← Назад | 1 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 600 | Дальше →

Вопрос по хешам. Объясните плиз на пальцах.

#1Arey
10.03.11 22:43
www.parser.ru → | ответить → | в избранное →

Вопрос по хешам. Объясните плиз на пальцах.

Здраствуйте уважаемые гуру и монстры парсера. Объясните пожалуйста несколько моментов с хешами кому не сложно... Раньше с ними как-то не работал, хватало таблиц, но сегодня решил разного рода данные хранящиеся в куки пихать не в таблицу, а в хеш. Прочитал документацию и честно говоря вошел в ступор, как то не укладывается у меня все в голове, поправьте если не прав...
Если с обычным хешем все понятно, так как фактически это таблица из двух столбцов и обращение к любой записи происходит по принципу ^table.locate[столбец всегда тот который содержит ключи;ключ] причем выдаем значение не этого столбца, а соседнего. Но вот я наткнулся на такую конструкцию:
$hash_of_hash[ 
   $.cat[ 
      $.food[milk] 
      $.aggressive[very] 
   ] 
   $.dog[ 
      $.food[bone] 
      $.aggressive[never] 
   ]
] 

То есть если я правильно понял что это фактически таблицы в таблице? Как тогда работает foreach?
И может ли существовать такая конструкция:
$hash_of_hash[ 
   $.cat[ 
      $.food[milk] 
      $.aggressive[very] 
   ] 
   $.dog[ 
      $.food[bone] 
      $.aggressive[never] 
   ]
   $.name[Вася] 
   $.age[22] 
   $.sex[m] 
] 

Если да, то как тут будет работать foreach?
Просьба не кидать помидорами если спросил элементарную вещь, но лучше спросить чем чувствовать себя идиотом...
Заранее спасибо за ответ.
#2Sumo
→ Arey [#1] | 10.03.11 22:50 / 22:53
www.parser.ru → | ответить → | в избранное →

Вы попробуйте сделать foreach и все станет понятно.

И хеш - это НЕ таблица из двух столбцов. Основное отличие состоит в том, что значение элемента хеша может быть любым парсеровским объектом (в том числе и другим хешем, что в примере и показано), а таблица может содержать исключительно строки.
#3Arey
→ Sumo [#2] | 10.03.11 23:25
www.parser.ru → | ответить → | в избранное →
Обязательно попробую, сейчас пока пытаюсь осознать сам принцип...
Т.е. значением может быть и картинка и таблица и строка и любой пользовательский метод? Я правильно понял? Честно говоря пока вопросов больше чем ответов в хелпе...
Заранее спасибо за ответ.
#4Arey
→ Sumo [#2] | 11.03.11 00:33
www.parser.ru → | ответить → | в избранное →

Поэкспериментировал, появился вопрос :)

Поэкспериментировал, конструкция
$hash_of_hash[ 
   $.cat[ 
      $.food[milk] 
      $.aggressive[very] 
   ] 
   $.dog[ 
      $.food[bone] 
      $.aggressive[never] 
   ]
   $.name[Вася] 
   $.age[22] 
   $.sex[m] 
] 

работает, можно обращаться по ключам. Также сделал foreach и возник вопрос как получить данные из такой конструкции:
$hash_of_hash[ 
   $.name_1[ 
      $.aid_1[1] 
      $.bid_1[1] 
   ] 
   $.name_2[ 
      $.aid_2[2] 
      $.bid_2[2] 
   ]
] 

name_1, name_2 неизвестны к ним надо как-то обратиться foreach естественно дает ошибку :(
Более того name_1 и name_2 необходимо использовать как значение переменной... Можно еще как то выкрутиться создав два хеша. В первом имена вложенных хешей второго, его перебирать и от него и адресоваться.
$hash_of_hash[ 
   $.name_1[ 
      $.aid_1[1] 
      $.bid_1[1] 
   ] 
   $.name_2[ 
      $.aid_2[2] 
      $.bid_2[2] 
   ]
   $.name_3[3] 
] 

А если появится еще и name_3 который не хеш в хеше, а просто элемент хеша, причем и его ключ и значение используются в переменных, вообще не представляю что делать.
Хотя может имеет смысл в таком случае использовать таблицу?
#5Misha v.3
→ Arey [#4] | 11.03.11 00:55
www.parser.ru → | ответить → | в избранное →
foreach естественно дает ошибку
для foreach вовсе не естественно давать ошибку.
ошибку может давать код, который согласно написанному, должен делать что-то странное (например "печатать" в output хэш).
вы попробуйте в foreach выводить просто ключи.

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

name_1, name_2 неизвестны к ним надо как-то обратиться
вообще-то основное назначение хэшей -- быстро получить значение по ключу (это делается гораздо быстрее, чем через locate у таблицы).
т.е. так:
$хэш.ключ1.ключ2.ключ3

значение ключа может быть в переменной:
$хэш.ключ1.[$переменная_с_именем_ключа2].ключ3


в вашем случае, вы похоже пытаетесь в лоб заменить таблицу на хэш, но я не понимаю, зачем вам это потребовалось. если таблицы вас устраивают, то хэши для решения _тех-же_ задач использовать незачем.
#6Arey
→ Misha v.3 [#5] | 11.03.11 13:31
www.parser.ru → | ответить → | в избранное →

Re: Согласен не прав, поясняю подробно...

Сорри виноват, конечно тут нет экстрасенсов...
И так задача:
Есть корзина интернет магазина с разноплановым товаром, причем у товара кроме одинаковых полей типа id-модели, id-цвета, цены, количества, есть еще такие поля как например цвет, который может быть, а может и отсутствовать, или например количество у какого-то товара может быть в единицах, а может быть и например в квадратных метрах причем количество дробное, или как еще вариант комплект чего-то котрый состоит из нескольких единиц и т.д и т.п.
Как использовать в данной ситуации таблицу я пока не придумал.
А вот "разнородный" хеш вида:
$hash_of_hash[ 
   $.name_1[ 
      $.aid_1[1] 
      $.bid_1[1] 
   ] 
   $.name_2[ 
      $.aid_2[2] 
      $.bid_2[2] 
      $.сid_2[2]
   ]
   $.name_3[ 
      $.aid_3[1]  
      $.сid_3[2]
   ]
   $.name_3[3] 
] 

Для этой задачи помоему наиболее подходящий вариант, так как таблица преполагает однородность данных. Возможно я конечно не прав, был бы крайне признателен за совет, может уже кто-то реализовывал такие задачи и есть более оптимальный путь, а я в силу неопытности опять все делаю далеко не самым простым способом.
Да, спасибо за совет выводить просто ключи, так работает...
#7max_rip
→ Arey [#6] | 11.03.11 18:24 / 18:27
www.parser.ru → | ответить → | в избранное →

С такой неоднородностью впору вам смотреть в сторону json и хранить его в БД.

+ написать себе метод разбора. Чтоб рекурсивно проходило по полям и выводило их.
вот можете посмотреть
«принцип работы $form:tables [debug.p]»
#8Misha v.3
→ Arey [#6] | 12.03.11 02:17 / 02:22
www.parser.ru → | ответить → | в избранное →
ваша задача всё равно не является той задачей, для которой действительно требуется применение хэша. попробую проиллюстрировать его использование на задаче вывода сообщения с тэгами.

сообщения, выводимые на страницы, находятся в таблице $tMessage (id, content) (это может быть и хэш, но мне, ввиду однородности данных, больше нравится таблица). теги -- в таблице $tTag (id, name).

а в таблице $tMessageToTag хранятся связи (message_id, tag_id). можно сразу доставать эти связи в виде хэша, но в этой демонстрации я буду использовать эти данные разными способами, поэтому для удобства демонстрации они в таблице.

для начала на основании таблицы $tMessageToTag формируем такой хэш:
$hMessageToTag[
	$.1[
		$.5(1)
		$.10(1)
		$.15(1)
	]
	$.2[
		$.5(1)
		$.6(1)
	]
	...
]

тут ключ первого уровня -- message_id, ключ второго -- tag_id. значение -- просто чтоб было (можно с пустыми значениями, но тогда проверка ниже будет немного другой).

далее так:
^tMessage.menu{
	<p>$tMessage.content</p>
	^tTag.menu{^if($hMessageToTag.[$tMessage.id].[$tTag.id]){<span>$tTag.name</span>}}[, ]
}


кстати подобную структуру в хэше бывает очень неудобно получать на основе данных, которые достаются из БД, поэтому иногда структуру хеша делают иной (с составным ключом):
$hMessageToTag[
	$.1=5(1)
	$.1=10(1)
	$.1=15(1)
	$.2=5(1)
	$.2=6(1)
	...
]

тут первая часть ключа (до разделителя, который я выбрал в виде символа '=') -- message_id, вторая часть -- tag_id.
подобный "плоский" хэш может быть получен из таблицы, полученной из БД с помощью единственной команды (будет получен хэш в котором более сложные значения, но на работоспособность подхода это не влияет):
$hMessageToTag[^tMessageToTag.hash{$tMessageToTag.message_id=$tMessageToTag.tag_id}]


код проверки наличия у сообщения определённого тэга меняется на следующий:
^if($hMessageToTag.[$tMessage.id=$tTag.id]){...}



но приведённый выше подход в общем случае плох. проблема в том, что у нас есть вложенный цикл с проверкой. если тэгов существенно больше, чем привязок, то внутренний цикл будет крутиться вхолостую, поэтому для устранения повторяющегося внутреннего холостого цикла лучше сделать [B]хэш таблиц[/B] с ключами message_id, а структуру с тэгами перевести в хэш (или сразу доставать из БД как хэш):

$hMessageTags[^tMessageToTag.hash[message_id][$.type[table] $.distinct(true)]]
$hTag[^tTag.hash[tag_id]]

^tMessage.menu{
	<p>$tMessage.content</p>
	^if($hMessageTags.[$tMessage.id]){
		^hMessageTags.[$tMessage.id].menu{
			<span>$hTag.[$hMessageTags.[$tMessage.id].tag_id].name</span>
		}[, ]
	}
}


в $hMessageTags будет следующая структура (ключами являются message_id, а значениями -- таблицы):
$hMessageTags[
	$.1[^table::create{message_id	tag_id
1	5
1	10
1	15}]

	$.2[^table::create{message_id	tag_id
2	5
2	6}]
]


P.S. приводимый код я не проверял и в нём возможны синтаксические или иные ошибки.
#9Arey
→ max_rip [#7] | 12.03.11 13:25
www.parser.ru → | ответить → | в избранное →

Корзина будет однозначно храниться в куках... Хотя почему бы и не в формате JSON...

#10Arey
→ Misha v.3 [#8] | 12.03.11 13:32
www.parser.ru → | ответить → | в избранное →

Спасибо за подробные пояснения

при помощи хеша хотел упростить проверку на наличие товара уже в корзине при попытке добавить второй раз одно и то же, и упростить процедуру удаления из корзины, т.е. банально хотел уйти от ^table.locate . Да и чего уж там греха таить хотел попробовать поработать с хешами т.к. раньше их не трогал... Но сейчас вижу что это была не самая лучшая идея, для этой задачи возможно лучше подходит таблица пусть с избыточным количеством полей...
#11Sumo
→ Arey [#9] | 12.03.11 15:53
www.parser.ru → | ответить → | в избранное →

А почему так категорично?

Мне показалось, что корзину удобнее хранить на сервере (две простенькие таблички для самих корзин и товаров в них), а в куках только идентификатор. В моем случае это позволяет безболезненно снимать товары с продажи (просто перемещаем их в "отложенные"), хранить дополнительную статистику и стоимость корзины (чтобы не возиться с этим при каждом запросе) и т.д. и т.п. Опять же корзина может быть неплохим идентификатором клиента, поскольку мы специально сделали работу с заказами без регистрации. Опять же нет проблемы с ограничением на размер кук.
#12Arey
→ Sumo [#11] | 12.03.11 22:27
www.parser.ru → | ответить → | в избранное →

Возможно вы и правы, а как Вы решили проблему с увеличением количества записей в этих таблицах? Можно подробнее про Вашу схему работы с корзиной?

#13Sumo
→ Arey [#12] | 12.03.11 22:39
www.parser.ru → | ответить → | в избранное →

О какой проблеме с количеством записей идет речь?

#14Arey
→ Sumo [#13] | 12.03.11 23:06
www.parser.ru → | ответить → | в избранное →

В двух таблицах где вы храните записи корзины...

При 1000 посетителей в день, добавивших в корзину по одному товару, через месяц 30 тысяч записей... По какому принципу вы их удаляете если клиент не удалил их сам? Можно конечно удалять записи кроном через какое-то время, но я планирую там хранить и некоторые настройки, например региональные... Хотя возможно имеет смысл принять стратегическое решение что если клиент ничего не сделал за месяц то это потерянный клиент и хранить его данные не стоит...
#15Sumo
→ Arey [#14] | 13.03.11 08:06
www.parser.ru → | ответить → | в избранное →

Ничего не удаляю...

Современные базы данных могут хранить в таблицах десятки и сотни миллионов записей совершенно без проблем. Кроме того, никто нам не мешает использовать технологии шардинга и денормализации данных, но до этого, даже при тысячах посетителей в день, дойдет не скоро.
#16Arey
→ Sumo [#15] | 13.03.11 10:25
www.parser.ru → | ответить → | в избранное →

Я понимаю что хранить можно, но зачем???

Я понимаю что хранить можно, но зачем хранить в базе мусор, рано или поздно это приведет не к очень хорошей ситуации... Я помню как года три назад в базе данных паспортно-визовой службы краснодарского края закончился диапазон чисел для автоинкремента, была большая проблема... Кстатит а что такое технология шардинга и денормализация данных? И еще, поделитесь пожалуйста опытом по какому принципу реализован поиск по Вашему сайту.
Заранее спасибо за ответ.
#17Sumo
→ Arey [#16] | 13.03.11 10:36 / 10:39
www.parser.ru → | ответить → | в избранное →

Удаление никак на автоинкремент не влияет...

Он нисколько не уменьшится, если удалить записи. Если вдруг не будет хватать 4 млрд. значений int unsigned, то всегда можно использовать bigint unsigned в качестве ключа - это очень много для любого магазина (64 bit, max = 18446744073709551615). :) Если и этого не хватит, то можно перейти на uuid (128 бит).

Поиск я реализовал через Sphinxsearch, из Парсера обращаюсь к нему через SphinxQL.

...что такое технология шардинга и денормализация данных?

Думаю про это лучше спросить у Яндекса - тема очень обширная. :)
#18Arey
→ Sumo [#17] | 13.03.11 11:15
www.parser.ru → | ответить → | в избранное →
Я понимаю про автоинкремент, я просто привел пример...
Понял спасибо...
#19Sumo
→ Arey [#18] | 13.03.11 17:19
www.parser.ru → | ответить → | в избранное →

Только из таких "примеров" выводы делать не стоит.

#20
→ Sumo [#19] | 14.03.11 11:36
www.parser.ru → | ответить → | в избранное →
Вы знаете, я пару дней подумал и наверно воспользуюсь все-таки Вашим методом, т.е. буду хранить у пользователя только ключ... Если Вы не против я буду задавать вопросы в случае их возникновения...
#21Sumo
14.03.11 11:43
www.parser.ru → | ответить → | в избранное →

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

#22
→ Sumo [#21] | 14.03.11 12:00
www.parser.ru → | ответить → | в избранное →

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

Страницы форума: ← Назад | 1 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 600 | Дальше →