У меня есть объект модели User с несколькими полями (свойствами, если хотите). Произнесите «имя», «фамилию», «город» и «год рождения». Каждый пользователь также получает «уникальный идентификатор».
Я хочу иметь возможность искать по ним. Как мне это сделать правильно? Как это сделать вообще?
Насколько я понимаю (будет работать практически для любого хранилища ключей-значений - сначала идет ключ, затем значение)
u: 123456789 = объект_сериализованного_json
(«u» — простой префикс для ключей пользователя, 123456789 — «уникальный идентификатор»).
Теперь, думая, что я хочу иметь возможность искать по имени и фамилии, я могу сохранить в:
f:Стив = u:384734807,u:2398248764,u:23276263 f:Alex = u:12324355,u:121324334
таким образом, ключ "f" - это префикс для имен, а "Стив" - это настоящее имя. Для "u:Steve" мы сохраняем как значение все идентификаторы пользователей, которые являются "Steve's".
Это делает каждый поиск очень-очень легким. Запрос по нескольким полям (свойствам) -- скажем, по имени (т. е. "Стив") и фамилии (т. е. "l:Anything") по-прежнему прост - сначала получите список идентификаторов пользователей из "f:Steve", затем список из "l :Anything", найдите пересекающиеся идентификаторы пользователей и вперед.
Проблемы (а их немало):
Сохранение, обновление, удаление пользователя - это боль. Это должна быть атомарная и последовательная операция. Кроме того, если у нас есть размер значения, ограниченный некоторым значением, то у нас (потенциальные) проблемы. И действительно не ответ здесь. Заархивировать только список идентификаторов пользователей? Впрочем, не слишком круто.
По какому идентификатору мы хотим добавить новое поле для поиска. В конце концов. Скажем "город". Мы конечно можем сделать так же "c:Los Angeles" = ..., "c:Chicago" = ..., но если мы не предусмотрели все эти "варианты поиска" с самого начала, то у нас будет чтобы иметь возможность создать какое-то ночное задание или что-то еще, чтобы пройтись по всем существующим записям пользователей и обновить для них эти "c:CITY"... Довольно большая работа!
Проблемы с блокировкой. Пользователь «u:123» обновляет свое имя «Алекс», а пользователь «u:456» обновляет свое имя «Алекс». Они оба должны обновить «f: Alex» со своими идентификаторами. То есть либо мы сталкиваемся с проблемой перезаписывания, либо одно обновление будет ждать другого (и визуализацию, если их много?!).
Как лучше всего это сделать? Имея в виду, что я хочу искать по многим полям?
P.S. Пожалуйста, вопрос касается хранилищ HBase/Cassandra/NoSQL/Key-Value. Пожалуйста, пожалуйста - никаких советов по использованию MySQL и «чтению» SELECT; и беспокоиться о проблемах масштабирования «позже». Есть причина, по которой я задал Свой вопрос именно так, как я это сделал. :-)