2015-12-07 3 views
1

Я хотел бы найти лучший матч с запросом mongo odm на Symfony. У меня есть функция, которая ищет объекты с массивом терминов.Найти лучший матч с Mongo ODM

Здесь в Exemple:

Я хочу найти всех пользователей, которые nammed «Пола», «Питер» и «Смит». Итак, мой массив $ search = array ('Paul', 'Peter', 'Smith');

У меня есть 3 пользователей, которые соответствуют этому запросу:

  • Питер Андерсон
  • Paul Smith
  • Пол Питер Смит

Так что я хотел бы, чтобы этот порядок запроса пользователи, как это :

  1. Paul Peter Smith
  2. Paul Smith
  3. Питер Андерсон

Вот мой текущий метод:

public function search($search) { 
    $query = $this->createQueryBuilder('AcmeDataBundle:users'); 
    $users = $query 
     ->field('name')->in($search) 
     ->getQuery()->execute(); 

    return $users; 
} 

Есть ли у вас какие-либо понятия о том, как я могу это сделать?

Благодаря

+1

Это не ответ на ваш вопрос, но вы действительно должны использовать правильный инструмент для поиска текста, search, lucene, solr –

+0

Использование инструмента поиска действительно лучше, но если вы хотите «забить» внутри mongodb, вы можете пойти по карте уменьшить: https://docs.mongodb.org/manual/core/map-reduce/ –

+0

@ RenatoMendesFigueiredo, да, я искал mapReduce, но я не понимаю, как это работает, и я не нахожу пример, который может мне помочь. – Shked0wn

ответ

1

Позволяет забыть о PHP и посмотреть, как мы можем добиться того, что с самой MongoDB (с использованием JS) первый.

Если вы хотите иметь функциональность «текстового поиска», вы должны указать , чтобы создать ИНДЕКС ТЕКСТА в поле, которое вы хотите найти. source

, что может быть достигнуто за счет:

db.yourCollectionName.createIndex({ fieldName: "text" })

После этого, когда вы сделать текст-поиска, вы будете иметь некоторые meta data связанные с запросом, который содержит некоторые оценки, которые MongoDB сгенерированные на основе о релевантности результатов по ключевым словам.

Итак, потому что вы хотите получить самый точный результат, мы должны только сортировать по этим оценкам.

В вашем случае это будет:

db.User.createIndex({ name: "text" }) 

db.User.find( 
    {$text:{$search:"Paul Smith Peter"}}, 
    { score: { $meta: "textScore" } } 
).sort({ score: { $meta: "textScore" } }); 

Хорошо. Это даст вам то, что вы хотите. но разрешите преобразовать его в стиль запроса Doctrine.

Для индекса:

/** 
* @ODM\Document 
* @ODM\Indexes({ 
* @ODM\Index(keys={"name"="text"}) 
* }) 
*/ 
class User{  
    /** @ODM\String */ 
    private $name; 

    //... 
} 

Затем запустите эту команду, чтобы обеспечить схему и индекс создаются:

php app/console doctrine:mongodb:schema:create

и заключительная часть:

$search = ['Paul', 'Peter', 'Smith']; 

$names = implode(' ', $search); 

$queryBuilder = $documentManager->createQueryBuilder('User'); 

$expr = $queryBuilder->expr()->operator('$text', array('$search' => $names)); 

$result = $queryBuilder 
      ->equals($expr->getQuery()) 
      ->sortMeta('score', 'textScore') 
      ->getQuery(); 

foreach ($result as $user) { 
    var_dump($user); 
} 
+0

Большое вам спасибо за отличный ответ! – Shked0wn

Смежные вопросы