#mongodb #mongodb-php #lithium
#mongodb #mongodb-php #литий
Вопрос:
У меня есть структура MongoDB, которая в настоящее время выглядит следующим образом:
[campaigns] => Array (
[0] => Array (
[campaign_id] => 4e8cba7a0b7aabea08000006
[short_code] => IHEQnP
[users] => Array (
)
)
[1] => Array (
[campaign_id] => 4e8ccf7c0b7aabe508000007
[short_code] => QLU_IY
[users] => Array (
)
)
)
Что я хотел бы иметь возможность делать, это искать короткий код и просто возвращать соответствующий массив. Сначала я пытался:
db.users.find({'campaigns.short_code':'IHEQnP'}, {'campaigns.campaign_id':1})
Однако это возвращает все массивы, а не только тот (или поле), который я хочу.
Есть ли в Mongo способ получить правильный массив (или даже поле, связанное с массивом)? Или это то, что я должен был бы сделать на сервере? Я использую платформу lithium для получения результатов (на случай, если это поможет).
Заранее спасибо 🙂
Dan
Ответ №1:
Когда вы используете критерии, такие как campaigns.short_code, вы все еще ищете коллекцию, campaigns — это просто свойство документа, ваша находка возвращает документы. Таким образом, учитывая эту структуру, вы не сможете достичь желаемого напрямую с помощью запроса.
Массивы в MongoDB можно нарезать, но не сортировать:
db.users.find({}, {campaigns: { $slice : 1}})
Это даст вам первую кампанию, но поскольку вы не можете ее отсортировать, поэтому IHEQnP находится на вершине, в этой ситуации это не поможет.
Подробнее читайте здесь.
Однако вы можете довольно просто отфильтровать это в Lithium после получения полного документа:
$id = 'id to match against';
$result = $user->campaigns->find(function($model) use ($id) {
return $model->campaign_id === $id
});
Смотрите Документы для Entity:: найти здесь
Моим решением было бы сохранить его у пользователя, если количество кампаний невелико (быстрая сортировка и фильтрация в PHP, если размер документа не слишком большой). Если ожидается, что это число будет расти, тогда подумайте о его перемещении в собственную модель / коллекцию или переосмыслите, как вы смоделировали свои данные.
Комментарии:
1. Спасибо за этот ответ — я раньше не видел второго используемого метода и не понимал, что могу выполнить внутренний поиск таким образом; что действительно полезно! Я нашел другой способ структурировать данные и найти необходимые данные (хотя и в двух вызовах БД). Я бы никогда не ожидал, что количество кампаний превысит 100 у каждого пользователя, но использование MongoDB оказалось немного сложнее, чем ожидалось, и, вероятно, следовало использовать MySQL для отношений (как и в случае с Mongo, у меня есть довольно много экземпляров повторяющихся данных в нескольких моделях). Еще раз спасибо! Обязательно проверю второй метод 🙂