Поиск по параметрам
От: J_K  
Дата: 19.07.09 06:51
Оценка:
Здравствуйте.
Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков:
1. Пользователь указывает значение параметров, выбранных произвольно (т.е. не все параметры могут быть указаны)
2. Данные отправляются на сервер и там обработчик должен отправить запрос к БД.
3??? Кто формирует запрос? Ясно, что это не может быть хранимая процедура, поскольку заранее неизвестно, какие параметры будут указаны. Можно составить запрос (строку) программным образом типа "если этот параметр присутствует, то включить его в строку, иначе нет" — но тогда получится запутанный и уродский код — потому что этот параметр надо указывать дважды, даже трижды — при вводе параметров, в самом запросе и потом при выводе данных. Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос. Но эта орм недешевое удовольствие и пока ее использование не планируется.
Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное.
Спасибо
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Re: Поиск по параметрам
От: Lloyd Россия  
Дата: 19.07.09 11:16
Оценка: 2 (1)
Здравствуйте, J_K, Вы писали:

J_K>Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос.


На LINQ-е будет ровно так же:
IQueriable<Товар> товары = ctx.Товары;
if (тип != nul)
  товары = товары.Where(т => т.тип == тип);
Re: Поиск по параметрам
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.07.09 18:58
Оценка: -3
Здравствуйте, J_K, Вы писали:

J_K>Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное.


Самая правильная тактика не делать такой уродский поиск. Или хотыб не называть это поиском.
Вы же гуглом пользуетесь, сколько там полей воода и кнопок?
И если в гугле написать "кемпинговая палатка на 4 человек с одним тамбуром", то они найдет именно такую палатку.
Re: Поиск по параметрам
От: knst Россия  
Дата: 19.07.09 19:36
Оценка:
Здравствуйте, J_K, Вы писали:

J_K>Здравствуйте.

J_K>Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков:
J_K>1. Пользователь указывает значение параметров, выбранных произвольно (т.е. не все параметры могут быть указаны)
J_K>2. Данные отправляются на сервер и там обработчик должен отправить запрос к БД.
J_K>3??? Кто формирует запрос? Ясно, что это не может быть хранимая процедура, поскольку заранее неизвестно, какие параметры будут указаны. Можно составить запрос (строку) программным образом типа "если этот параметр присутствует, то включить его в строку, иначе нет" — но тогда получится запутанный и уродский код — потому что этот параметр надо указывать дважды, даже трижды — при вводе параметров, в самом запросе и потом при выводе данных. Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос. Но эта орм недешевое удовольствие и пока ее использование не планируется.
J_K>Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное.
J_K>Спасибо

Например можно передавать NULL в тех местах где параметр не задан а в where: PARAM=@PARAM OR @PARAM is NULL
Вряд ли нужно искать палатки для которых не известно кол-во мест(если нужно, запрос будет чутьсложнее но тож решаемо)
И кстати лучше это делать не запросом а хранимкой, так оно со всех сторон вернее — быстрее, нет хардкода запроса и грязи в коде, ошибки в запросе можно исправить не передеплоивая код, быстрее наконец.
Re[2]: Поиск по параметрам
От: J_K  
Дата: 19.07.09 20:03
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, J_K, Вы писали:


J_K>>Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное.


G>Самая правильная тактика не делать такой уродский поиск. Или хотыб не называть это поиском.


Ну скажите это ребятам из yandex.market. У них это реализовано именно так и работает.

G>Вы же гуглом пользуетесь, сколько там полей воода и кнопок?

G>И если в гугле написать "кемпинговая палатка на 4 человек с одним тамбуром", то они найдет именно такую палатку.

Увы, ничего ваш гугль не найдет. Проверено на себе лично безуспешными поисками некоторых вещей.
Во-вторых, лично я не люблю писать. Да, я не люблю писать! Я могу ошибиться, я могу забыть что-то. Если поиск знает все параметры, гораздо проще сделать несколько кликов, чем вписывать. Попробуйте написать "кемпинговая палатка на 4 человек с одним тОмбуром" и вы получите в ответ молчание. В данном топике обсуждаются не плюсы-минусы данного подхода, а как это реализовать. Давайте уж придерживаться темы, что ли.
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Re[2]: Поиск по параметрам
От: J_K  
Дата: 19.07.09 20:15
Оценка:
Здравствуйте, knst, Вы писали:

K>Здравствуйте, J_K, Вы писали:


J_K>>Здравствуйте.

J_K>>Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков:
J_K>>1. Пользователь указывает значение параметров, выбранных произвольно (т.е. не все параметры могут быть указаны)
J_K>>2. Данные отправляются на сервер и там обработчик должен отправить запрос к БД.
J_K>>3??? Кто формирует запрос? Ясно, что это не может быть хранимая процедура, поскольку заранее неизвестно, какие параметры будут указаны. Можно составить запрос (строку) программным образом типа "если этот параметр присутствует, то включить его в строку, иначе нет" — но тогда получится запутанный и уродский код — потому что этот параметр надо указывать дважды, даже трижды — при вводе параметров, в самом запросе и потом при выводе данных. Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос. Но эта орм недешевое удовольствие и пока ее использование не планируется.
J_K>>Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное.
J_K>>Спасибо

K>Например можно передавать NULL в тех местах где параметр не задан а в where: PARAM=@PARAM OR @PARAM is NULL

K>Вряд ли нужно искать палатки для которых не известно кол-во мест(если нужно, запрос будет чутьсложнее но тож решаемо)
K>И кстати лучше это делать не запросом а хранимкой, так оно со всех сторон вернее — быстрее, нет хардкода запроса и грязи в коде, ошибки в запросе можно исправить не передеплоивая код, быстрее наконец.

В том-то и дело, что нужно искать и палатки, для которых неизвестно количество мест. Может, я хочу прикинуть разницу между палаткой на трех и четырех человек. Т.е. суть задачи в том, что заранее набор параметров неизвестен. Соглашусь, что параметров также не должно быть слишком много, но даже если их будет в пределах десяти, и они будут разные — например, один параметр — это строка, другой — значение (списка), третий — в промежутке от N до M — это сильно усложняет задачу в целом.
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Re[2]: Поиск по параметрам
От: Lloyd Россия  
Дата: 19.07.09 20:16
Оценка:
Здравствуйте, knst, Вы писали:

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


Только вот скорость исполнения этого запроса будет далека от оптимальной
Re: Поиск по параметрам
От: baranovda Российская Империя  
Дата: 19.07.09 20:43
Оценка:
Здравствуйте, J_K, Вы писали:

J_K>Здравствуйте.

J_K>Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков:

Тут всё просто и понятно.
Хранилище данных или объектная модель должны предоставлять свое метаописание в таком качестве, чтобы автомат мог по метаописанию 1) построить пользователю гуй формы запроса 2) смастерить дерево выражений параметров поиска и фильтрации и скормить его автомату, выполняющему запрос. Этот функционал отлично реализован, например, в 1С-ке.
Re[2]: Поиск по параметрам
От: J_K  
Дата: 19.07.09 20:45
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Здравствуйте, J_K, Вы писали:


J_K>>Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос.


L>На LINQ-е будет ровно так же:

L>
L>IQueriable<Товар> товары = ctx.Товары;
L>if (тип != nul)
L>  товары = товары.Where(т => т.тип == тип);
L>


Мне кажется, тут не совсем так. Псевдокод должен быть примерно таким:
if (@param1 != null)
where += param1 == @param1
if (param2 != null)
where += param2 == @param2

Ну и так далее. Честно, я плохо знаю возможности linq с этой т.з. Т.е задача состоит в том, чтобы составить запрос, когда состав и значение параметров заранее неизвестны.
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Re[3]: Поиск по параметрам
От: Lloyd Россия  
Дата: 19.07.09 20:52
Оценка: +1
Здравствуйте, J_K, Вы писали:

L>>На LINQ-е будет ровно так же:

L>>
L>>IQueriable<Товар> товары = ctx.Товары;
L>>if (тип != nul)
L>>  товары = товары.Where(т => т.тип == тип);
L>>


J_K>Мне кажется, тут не совсем так. Псевдокод должен быть примерно таким:

J_K>if (@param1 != null)
J_K> where += param1 == @param1
J_K>if (param2 != null)
J_K> where += param2 == @param2

Нет, вы ошибаетесь. Код буде именно такой как написано выше.

J_K>Ну и так далее. Честно, я плохо знаю возможности linq с этой т.з. Т.е задача состоит в том, чтобы составить запрос, когда состав и значение параметров заранее неизвестны.


Именно это приведенный код и делает.
Re[4]: Поиск по параметрам
От: J_K  
Дата: 20.07.09 02:48
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Здравствуйте, J_K, Вы писали:


L>>>На LINQ-е будет ровно так же:

L>>>
L>>>IQueriable<Товар> товары = ctx.Товары;
L>>>if (тип != nul)
L>>>  товары = товары.Where(т => т.тип == тип);
L>>>


J_K>>Мне кажется, тут не совсем так. Псевдокод должен быть примерно таким:

J_K>>if (@param1 != null)
J_K>> where += param1 == @param1
J_K>>if (param2 != null)
J_K>> where += param2 == @param2

L>Нет, вы ошибаетесь. Код буде именно такой как написано выше.


J_K>>Ну и так далее. Честно, я плохо знаю возможности linq с этой т.з. Т.е задача состоит в том, чтобы составить запрос, когда состав и значение параметров заранее неизвестны.


L>Именно это приведенный код и делает.


Не могли бы вы использовать более понятные обозначения? Скажем, пусть тип товары будет Tents, а параметры parameter1, parameter2. А то я сколько ни пялюсь, не могу увидеть в вашем коде несколько параметров. Спасиб
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Re[2]: Поиск по параметрам
От: J_K  
Дата: 20.07.09 03:51
Оценка:
Здравствуйте, baranovda, Вы писали:

B>Здравствуйте, J_K, Вы писали:


J_K>>Здравствуйте.

J_K>>Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков:

B>Тут всё просто и понятно.

B>Хранилище данных или объектная модель должны предоставлять свое метаописание в таком качестве, чтобы автомат мог по метаописанию 1) построить пользователю гуй формы запроса 2) смастерить дерево выражений параметров поиска и фильтрации и скормить его автомату, выполняющему запрос. Этот функционал отлично реализован, например, в 1С-ке.

Допускаю, что в 1с реализовано если не все, то большинство из того, что мне нужно... но использование 1с исключено по ряду причин.
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Re[5]: Поиск по параметрам
От: Lloyd Россия  
Дата: 20.07.09 07:06
Оценка: :))
Здравствуйте, J_K, Вы писали:

L>>Именно это приведенный код и делает.


J_K>Не могли бы вы использовать более понятные обозначения? Скажем, пусть тип товары будет Tents, а параметры parameter1, parameter2. А то я сколько ни пялюсь, не могу увидеть в вашем коде несколько параметров. Спасиб


IQueriable<Tent> q = ctx.Tents;
if (parameter1 != null)
  q = q.Where(t => t.parameter1 == parameter1);
if (parameter2 != null)
  q = q.Where(t => t.parameter2 == parameter2);
Re[6]: Поиск по параметрам
От: J_K  
Дата: 20.07.09 19:19
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Здравствуйте, J_K, Вы писали:


L>>>Именно это приведенный код и делает.


J_K>>Не могли бы вы использовать более понятные обозначения? Скажем, пусть тип товары будет Tents, а параметры parameter1, parameter2. А то я сколько ни пялюсь, не могу увидеть в вашем коде несколько параметров. Спасиб


L>
L>IQueriable<Tent> q = ctx.Tents;
L>if (parameter1 != null)
L>  q = q.Where(t => t.parameter1 == parameter1);
L>if (parameter2 != null)
L>  q = q.Where(t => t.parameter2 == parameter2);
L>


Спасибо, буду разбираться!

А у меня еще такой вопрос созрел (почти безотносительно текущего) — есть два подхода. Первый — использовать готовую ХП, второй — генерировать ее на лету. Как вы думаете, какой подход лучше с т.з. производительности?
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Re[7]: Поиск по параметрам
От: Lloyd Россия  
Дата: 20.07.09 22:19
Оценка:
Здравствуйте, J_K, Вы писали:

J_K>А у меня еще такой вопрос созрел (почти безотносительно текущего) — есть два подхода. Первый — использовать готовую ХП, второй — генерировать ее на лету. Как вы думаете, какой подход лучше с т.з. производительности?


Второй вариант лучше, т.к. производительность запросов зависит в частности от того, насколько у них "хороший" план.
Если у вас один запрос на все случаи (как в варианте с хранимкой), то и план будет один и получить хороший план для любого набора входных параметров не получится.
Если же вы генерите запросы на лету (как в варианте с LINQ-ом), то для разного набора параметров фильтрации будут сформированы разные запросы и план выполнения будет лучше.
Re[8]: Поиск по параметрам
От: J_K  
Дата: 21.07.09 06:04
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Здравствуйте, J_K, Вы писали:


J_K>>А у меня еще такой вопрос созрел (почти безотносительно текущего) — есть два подхода. Первый — использовать готовую ХП, второй — генерировать ее на лету. Как вы думаете, какой подход лучше с т.з. производительности?


L>Второй вариант лучше, т.к. производительность запросов зависит в частности от того, насколько у них "хороший" план.

L>Если у вас один запрос на все случаи (как в варианте с хранимкой), то и план будет один и получить хороший план для любого набора входных параметров не получится.
L>Если же вы генерите запросы на лету (как в варианте с LINQ-ом), то для разного набора параметров фильтрации будут сформированы разные запросы и план выполнения будет лучше.

Хм... интересно, подумаю. Спасибо
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Re[3]: Поиск по параметрам
От: knst Россия  
Дата: 23.07.09 10:14
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Здравствуйте, knst, Вы писали:


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


L>Только вот скорость исполнения этого запроса будет далека от оптимальной


Ну не сказал бы что генерация sql на лету будет быстрее. Параметров ограниченное количество, сделать правильные индексы не сложно.
Да и если речь идет о товарах в магазине, то объем данных небольшой, можно и не заморачиваться с оптимизацией — поиск идет по максимум 10000 записей, это не объем для БД, все будет летать даже если запрос кривой. Если б объемы были большими порекомендовал бы OLAP (Хотя тут как с нейросетями — идея кажется красивой и всеобъемлющей на первый взгляд а как пытаешься копнуть глубже выясняется что подходит только для небольшого кол-ва частных случаев).
Re[4]: Поиск по параметрам
От: J_K  
Дата: 23.07.09 17:58
Оценка:
Здравствуйте, knst, Вы писали:

K>Здравствуйте, Lloyd, Вы писали:


L>>Здравствуйте, knst, Вы писали:


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


L>>Только вот скорость исполнения этого запроса будет далека от оптимальной


K>Ну не сказал бы что генерация sql на лету будет быстрее. Параметров ограниченное количество, сделать правильные индексы не сложно.

K>Да и если речь идет о товарах в магазине, то объем данных небольшой, можно и не заморачиваться с оптимизацией — поиск идет по максимум 10000 записей, это не объем для БД, все будет летать даже если запрос кривой. Если б объемы были большими порекомендовал бы OLAP (Хотя тут как с нейросетями — идея кажется красивой и всеобъемлющей на первый взгляд а как пытаешься копнуть глубже выясняется что подходит только для небольшого кол-ва частных случаев).

Речь идет о товарах, но не в магазине — сервис вроде поисковой системы. Мы сами ничего не продаем, а только предоставляем возможность найти и сравнить. Поэтому товаров может быть не много, а очень много. Впрочем, я не думаю, что существует какая-то принципиальная разница между генерацией скрипта и использованием уже готового. Компы сейчас быстрые, а в производительности участвует так много факторов, что разница между этими двумя подходами незначительна.
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Re[4]: Поиск по параметрам
От: Lloyd Россия  
Дата: 23.07.09 18:58
Оценка: +2 -1
Здравствуйте, knst, Вы писали:

L>>Только вот скорость исполнения этого запроса будет далека от оптимальной


K>Ну не сказал бы что генерация sql на лету будет быстрее.


Гораздо быстрее.

K>Параметров ограниченное количество, сделать правильные индексы не сложно.


Не поможет. Можно хоть обвешаться индексами, но если оптимизатор построил план, в котором используется индекс по полю A, а фактически ты ищешь по B, то индекс не поможет.
Re[5]: Поиск по параметрам
От: knst Россия  
Дата: 24.07.09 10:41
Оценка:
J_K>Речь идет о товарах, но не в магазине — сервис вроде поисковой системы. Мы сами ничего не продаем, а только предоставляем возможность найти и сравнить. Поэтому товаров может быть не много, а очень много. Впрочем, я не думаю, что существует какая-то принципиальная разница между генерацией скрипта и использованием уже готового. Компы сейчас быстрые, а в производительности участвует так много факторов, что разница между этими двумя подходами незначительна.

В таком случае можно поизобретать велосипеды например ввести понятие хэш кода расчитывающегося на основании полей и делать выборку в два этапа — сначала на стороне сервера вычисляем хэш код фильтруем по нему а уже в пределах найденного уточняем поиск или взять готовый велосипед на базе MapReduce (например Aster nCluster или Hadoop).

Хотя опять же, что значит очень много... на нескольких миллионах БД по прежнему вполне шустро выполняет запросы.
Возможно я не прав, но у меня сложилось впечатление, что ты пытаешься решить проблему , которая еще не возникла, оптимизировать стоит уже написанные запросы если они тормозят, а не пытаться изначально усложнить систему с целью повысить быстродействие. Ботлнек может оказаться совсем не на стороне базы.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.