Пользовательский ввод для поиска MongoDB

1

В настоящее время я пытаюсь принять пользовательский ввод, чтобы пользователь мог выполнять поиск в базе данных.

> db.test2.find().pretty()
{
    "_id" : ObjectId("55de8a17f8389e208a1e7d7e"),
    "name" : "john",
    "favorites" : {
        "vegetable" : "spinach",
        "fruit" : "apple",
    }
}
{
    "_id" : ObjectId("55de8a17f8389e208a1f6gg4"),
    "name" : "becky",
    "favorites" : {
        "vegetable" : "spinach",
        "fruit" : "apple",
    }
}
{
    "_id" : ObjectId("55e3b6cbec2740181355b809"),
    "name" : "liz",
    "favorites" : {
        "vegetable" : "spinach",
        "fruit" : "banana",
    }
}

В этом примере пользователь сможет искать любую комбинацию любимого овоща, фруктов или любимых овощей и любимых фруктов. Если пользователь вошел в шпинат для любимого овоща, все три будут возвращены. Однако, если пользователь вводит любимый овощ = шпинат и любимый фрукт = яблоко, будут возвращены только джон и беки.

В MongoDB вы можете определить, какой параметр вы хотите искать. Я пытаюсь написать свой код таким образом, что если пользователь оставляет поле пустым, его не следует искать.

я пытался

$query = array("favorites.vegetable" => "$userInput", "favorites.fruit" => "$userInput2");

но если одно из этих полей остается пустым, оно не вернет никаких результатов. Я думал о том, чтобы использовать инструкции if:

if ($vegetable == NULL)
{
    $query = array("favorites.fruit" => "$fruit");
}

else if($fruit == NULL)
{
    $query = array("favorites.vegetable" => "$vegetable");
}

else
{
    $query = array("favorites.vegetable" => "$vegetable", "favorites.fruit" => "$fruit");
}

но если бы я хотел сделать свою базу данных доступной для поиска по более параметрам, у меня было бы слишком много условных операторов. Есть ли способ сделать мой поиск в Монго, когда поле остается пустым?

Теги:
mongodb-query

1 ответ

0
Лучший ответ

На самом деле возникает вопрос: "Откуда поступает вход?". Как будто у вас есть какая-то структура для ввода, тогда кодирование довольно просто следовать шаблону.

Как бы то ни было, с двумя основными переменными вы можете очистить код, чтобы просто конкретизировать свой запрос на основе того, что находится в переменных:

$query = array();

if ( $fruit != NULL ) {
    $query["favorites.fruit"] = $fruit;
}

if ( $vegetable != NULL ) {
    $query["favorites.vegetable"] = $vegetable;
)

Это означает, что вы либо закончите с $query здесь, либо пустым, чтобы соответствовать всем, либо содержат конкретные аргументы (один или два) в зависимости от того, был ли контент нулевым или нет.

Если ваш ввод имеет некоторую структуру, то вы можете быть намного более динамичным:

$input = array("fruit" => "apple", "vegetable" => "spinach");

$query = array();

foreach ( $input as $key => $value ) {
    $query["favorites.$key"] = $value;
}

Что делает то же самое, добавляя к $query но более динамически, чем с отдельными переменными.

Также обратите внимание, что в отношении MongoDB ваша структура документа невелика. Вероятно, это должно выглядеть так:

{
    "_id" : ObjectId("55de8a17f8389e208a1e7d7e"),
    "name" : "john",
    "favorites" : [
        { "type": "vegetable", "name": "spinach" },
        { "type": "fruit", "name": "apple" }
    ]
}

И хотя сначала может показаться, что запрос выходит сложнее, удаление "конкретных путей" в вашем запросе для таких ключей, как "овощ" и "фрукты", имеет много преимуществ, которые облегчают жизнь, а также primarilly "данные" могут быть "проиндексированы". Имена ключей не индексируются для поиска и, следовательно, неэффективны:

$input = array("fruit" => "apple", "vegetable" => "spinach");

$query = array();

foreach ( $input as $key => $value ) {
  $query['$and'][] = array(
    'favorites' => array(
      '$elemMatch' => array(
          'type' => $key, 'name' => $value
      )
    )
  );
}

Какой хороший запрос использует $elemMatch для поиска документов, содержащих "все" элементы массива, где "оба" "тип" и "имя" указанных элементов в вашем списке ввода.

В основном это похоже на JSON:

{
  "$and": [
    { "favorites": {
      "$elemMatch": {
          "type": "fruit", "name": "apple"
      }
    }},
    { "favorites": {
      "$elemMatch": {
          "type": "vegetable", "name": "spinach"
      }
    }}
  ]
}

Все сводится к пониманию того, как манипулировать структурами данных на выбранном вами языке, и что "структуры данных" - это все запросы MongoDB, насколько это касается вашего языка.

Что касается изменения структуры, то кондите, что поиск людей, у которых есть "овощи" в своих "фаворитах", теперь становится следующим:

{ "favorites.type": "vegetable" }

Что хорошо, так как "favorite.type" можно индексировать, а не:

{ "favorites.vegetable": { "$exists": true } }

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

  • 0
    Большое спасибо за ваш подробный ответ! Это действительно помогло мне. Я приму во внимание, как я структурирую свои базы данных. Еще раз спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню