Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Вариации данных в массиве
Форумы портала PHP.SU » » Хранение данных, их вывод и обработка » Вариации данных в массиве

Страниц (1): [1]
 

1. SunChase - 10 Ноября, 2011 - 17:21:12 - перейти к сообщению
Доброго времени суток.

Поступила задачка отыскать в базе данных пользователей записи, пытаясь найти все совпадения. Знаю что прозвучало это слегка "загадочно", потому попросту перейду к примеру:

Человек пытается найти запись: Карлов Иван Исаакович

Вводя это в строку поиска, система получает одну целую строку, разбивает её элементы массива, ориентируясь на пробел, все лишние элементы отсекает, и пытается найти всевозможные вариации строки Карлов Иван Исаакович, а именно:

Карлов Иван Исаакович
Иван Карлов Исаакович
Исаакович Иван Карлов
Карлов Иван
Иван Карлов
...
Исаакович
...

Разбить массив на элементы, отсечь лишнее и вручную вписать все вариации запросов к БД, ориентируясь на первоначальное к-во элементов(допустим их не 3 а 2 или 1), конечно можно, но хотелось бы услышать ответ на вопрос: Можно ли както автоматизировать процесс перебора элементов массива?

Заранее благодарен за любую полезную информацию.
2. Stierus - 10 Ноября, 2011 - 17:30:05 - перейти к сообщению
Я бы хранил ключ, который был бы md5 от отсортированных ФИО и искал по ним, не ?

скажем так:

Иванов
Акакий
Валерьевич

приводилось бы к md5(АкакийВалерьевичИванов) и сохранялось

Яковлев
Шамиль
Арсеньевич

приводилось бы к md5(АрсеньевичШамильЯковлев)

и тд

Это если решать вашу задачу в лоб, а так можно и над более элегантным решением подумать ... к чему это я? К тому, что у вас задача первоначально немного иная - найти совпадения, может быть решена более простым и быстрым вариантом Улыбка
(Добавление)
разбить строку в массив http://ru.php.net/manual/en/function.explode.php
пройтись по массиву foeach()
Ну или регулярки
3. SunChase - 10 Ноября, 2011 - 17:39:08 - перейти к сообщению
foreach если не ошибаюсь ориентирован на каждый элемент массива в отдельности, и будет иметь к-во циклов, равное к-ву элементов массива(поправьте, если неправ), тобиш 3. Тут же из 3х элементов получается как минимум 14 вариантов...

Конечно можно воспользоваться foreach и применить для поиска каждый элемент в роле Фамилии, Имя или Отчества, но это будет иметь меньшую точность...
4. DeepVarvar - 10 Ноября, 2011 - 17:57:39 - перейти к сообщению
А что мешает динамически нарисовать запрос вида:
CODE (SQL):
скопировать код в буфер обмена
  1. WHERE f1 LIKE '%фыва%' OR f2 LIKE '%фыва%' OR ... fN LIKE '%фыва%'

Количество полей известно заранее и равно трем.
Задача не тривиальна..
Если искать по трем словам, то к каждому полю всего три варианта LIKE..
А чтобы не искали по длинным словам, резать их, а чтобы не искали по 10 словам (такое только гугл себе позволить может), ограничиваться максимум, скажем, четырьмя первыми.
(Добавление)
Еще есть оч хорошая штука - FULLTEXT
5. EuGen - 10 Ноября, 2011 - 18:02:51 - перейти к сообщению
А если есть
Петр Иванов
Сидор Петрович
Федор Иванов

- то по запросу "Петр Иванов" - рано или поздно будет поиск просто по "Иванов" и "Петр".
Так вот, в первом случае - должна ли система найти "Федор Иванов" а во втором - "Сидор Петрович"?
6. SunChase - 10 Ноября, 2011 - 18:10:26 - перейти к сообщению
А в том то и дело, что в случае:

f1 like "%bla1%" or f2 like "%bla2%" or f3 like "%bla3%"

я получу "рулон", где хотябы одно из like подошло по условию, то есть на запрос Петя Васячкин Иванов, я получу на кучу всех Васячкинов,Ивановов и Петь. У меня же задача лежит "выловить" всё, постепенно отделяя по одному элементу из массива, тобиш:

f1 like "%bla1%" and f2 like "%bla2" and f3 like "%bla3"
....
f1 like "%bla3%" and f2 like "%bla1%"
...

тоесть сначала я получу все доступные записи по Пети Васячкине Иванове во всех вариациях, потом по Пети Васячкине и т.д.
7. DeepVarvar - 10 Ноября, 2011 - 18:18:15 - перейти к сообщению
И сколько запросов делать намерены?
8. SunChase - 10 Ноября, 2011 - 18:20:13 - перейти к сообщению
DeepVarvar пишет:
И сколько запросов делать намерены?


Знаю, что делать 14 запросов ради того, чтобы отыскать человека, маленько попахивает "бредовостью", но интереса ради хотелось бы увидеть как вообще можно реализовать поставленную задачу
9. DeepVarvar - 10 Ноября, 2011 - 18:38:00 - перейти к сообщению
PHP:
скопировать код в буфер обмена
  1. $q = "Терехова Даздраперма Ивановна";
  2. $arr = explode(" ",$q);
  3. $s = "SELECT * FROM tbl WHERE f1 LIKE '%".implode("%' OR f1 LIKE '%",$arr)."%'";
10. Stierus - 10 Ноября, 2011 - 19:22:12 - перейти к сообщению
Аааа, ясно что вы хотите Улыбка

вам нужен snowball stemming algorithm. разбор на слова, приведение к словоформам и индексация в отдельной таблице. Когда вам нужно будет найти - выгребаете все, куда ведет хотя бы 1 из слов и сортируется по количеству упоминаний в выборке. Более продвинутые алгоритмы ранжирования будут излишне
11. tuareg - 10 Ноября, 2011 - 19:54:57 - перейти к сообщению
Добавьте три поля типа int(11)
И при сохранении делайте поле1=CRS32('поле1') поле2=CRS32('поле2')и т.д
Тогда запрос будет при трех параметрах
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT * FROM TABLE pole1 IN (CRS32('pole1'),CRS32('pole2'),CRS32('pole3')) OR pole2 IN (CRS32('pole1'),CRS32('pole2'),CRS32('pole3')) OR pole3 IN (CRS32('pole1'),CRS32('pole2'),CRS32('pole3'))
  3.  

И уже потом PHP фильтруем как надо.
LIKE долго и не оптимально, здесь плюс используем индекс
Да и еще по условию(топик читал, но не викал) если точно знаем что вводятся 3 значения но не знаем порядок тогда просто добавляем одно поле int(11) при сохранении делаем CRS32('вся строка') и при запросе будет просто перебор возможных вариантов
12. SunChase - 10 Ноября, 2011 - 21:05:20 - перейти к сообщению
сделал вариации условия поиска согласно к-ву слов(не стал вдаваться в подробности с уменьшением к-ва элементов). Вроде бы всё нормально находит. Всем спасибо за информацию

 

Powered by ExBB FM 1.0 RC1