2013-04-23 6 views
1

Я хочу сделать функцию поиска в PHP и MSSQL с помощью драйвера SQLSRV.PHP Поиск человека с взрывом

У меня есть только одно поле ввода поиска на странице. Я хочу найти людей в моей таблице под названием «Персоны» и следующие столбцы: SSN, имя, фамилия

Проблема в том, что один человек может иметь один или несколько имен в столбце Firstname.

Я хочу также выполнять поиск по одиночным строкам типа: Только первое имя или только имя (-ы) или фамилия.

Как я могу это сделать? Должен ли я использовать функцию explode в PHP?

+0

Если вы не доработаете свою модель данных, вы получите очень медленный поиск, потому что в какой-то момент вам придется выполнять строковые операции на весь ваш набор данных. –

+0

Зачем? Также, если я использую explode для изменения запросов LIKE –

+0

Вы только что сказали, что ваш первый столбец имени может содержать «John Joe Jack James Joaquin». Если вы хотите искать только имена миддлэнов, вам придется отключить «Джон». Во всех рядах. Очевидно, что вы можете сделать «LIKE»% James% ', а потом проверить строки, где это не первое имя в этом столбце ... но это тоже будет медленным. –

ответ

0

Я бы предложил создать индекс поиска.

В дальнейшем я предполагаю, что ваш persons таблица выглядит следующим образом:

| person_id | firstname | lastname | ssn | 

Чтобы иметь возможность построить индекс поиска, вы будете нуждаться в person_searchindex таблицу для этого:

| person_id | search_term | 

Вы мог бы использовать что-то вроде этого: (Это всего лишь очень первый эскиз.)

<?php 
function addTermToSearchIndex($person_id, $term) 
{ 
    performQuery("INSERT INTO person_searchindex (person_id, search_term) 
        VALUES (" . (int)$person_id . ", ". 
        "\"" . escapeForQuery($term) . "\");"); 
} 

function buildSearchIndexForPerson($person_id, $firstname, $lastname, $ssn) 
{ 
    $firstnames = explode(" ", $firstname); 
    foreach($firstnames => $name) 
    { 
     addTermToSearchIndex($person_id, $name); 
    } 

    $lastnames = explode(" ", $lastname); 
    foreach($lastnames => $name) 
    { 
     addTermToSearchIndex($person_id, $name); 
    } 

    addTermToSearchIndex("$ssn"); 
} 

function deleteSearchIndexForPerson($person_id) 
{ 
    performQuery("DELETE FROM person_searchindex WHERE person_id = " . (int)$person_id . ";"); 
} 

function rebuildSearchIndexForPerson($person_id, $firstname, $lastname, $ssn) 
{ 
    deleteSearchIndexForPerson($person_id); 
    buildSearchIndexForPerson($person_id, $firstname, $lastname, $ssn); 
} 

function rebuildSearchIndex() 
{ 
    performQuery("DELETE FROM person_searchindex;"); 
    $result = performQuery("SELECT * FROM persons;"); 
    while($row = getRow($result)) 
    { 
     buildSearchIndexForPerson($ow["person_id"], $row["firstname"], $row["lastname"], $row["ssn"]); 
    } 
} 

function search($searchterm) 
{ 
    $sqlcond = "FALSE"; 

    $terms = explode(" ", $searchterm); 
    foreach($terms => $term) 
    { 
     $sqlcond .= " OR s.search_term LIKE \"%" . escapeForQuery($term) . "%\""; 
    } 

    return performQuery("SELECT p.person_id, p.firstname, p.lastname, p.ssn FROM persons AS p LEFT JOIN person_searchindex AS s ON p.person_id = s.person_id WHERE $sqlcond;"); 
} 

?> 

Добавьте вызов метода rebuildSearchIndexForPerson() всякий раз, когда вы добавляете или меняете строку человека. Добавьте вызов метода deleteSearchIndexForPerson() всякий раз, когда вы удаляете строку пользователя. В первый раз, когда вы когда-либо захотите что-то искать, вам нужно позвонить rebuildSearchIndex(), чтобы создать индекс поиска для ваших старых строк. После этого вы сможете использовать функцию search().

Как я уже сказал, это всего лишь очень первый эскиз. Например, вам нужно будет изменить методы performQuery, escapeForQuery и getRow на то, что вы на самом деле будете использовать. Кроме того, качество php-кода не является особенно хорошим. Но картина того, как она работает, должна стать ясной.