2014-02-09 3 views
2

Скажем, у меня есть коллекция users в MongoDB. Типичный пользовательский документ содержит поле имени и массив поддокументов, представляющих характеристики пользователя. Скажите что-нибудь вроде этого:MongoDB - сортировать по поддокументному совпадению

{ 
    "name": "Joey", 
    "characteristics": [ 
     { 
      "name": "shy", 
      "score": 0.8 
     }, 
     { 
      "name": "funny", 
      "score": 0.6 
     }, 
     { 
      "name": "loving", 
      "score": 0.01 
     } 
    ] 
} 

Как я могу найти лучшие пользователь X смешных, отсортированный по тому, как смешно они?

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

db.users.aggregate([ 
    {$project: {"_id": 1, "name": 1, "characteristics": 1, "_characteristics": '$characteristics'}}, 
    {$unwind: "$_characteristics"}, 
    {$match: {"_characteristics.name": "funny"}}, 
    {$sort: {"_characteristics.score": -1}}, 
    {$limit: 10} 
]); 

который, кажется, именно то, что я хочу, за исключением того факта, что, согласно до MongoDB's documentation on using indexes in pipelines, как только я вызываю $project или $unwind в конвейере агрегации, я больше не могу использовать индексы для сопоставления или сортировки коллекции, что делает это решение несколько неосуществимым для очень большой коллекции.

ответ

1

Я думаю, что вы на полпути. Я хотел бы сделать

db.users.aggregate([ 
    {$match: { 'characteristics.name': 'funny' }}, 
    {$unwind: '$characteristics'}, 
    {$match: {'characteristics.name': 'funny'}}, 
    {$project: {_id: 0, name: 1, 'characteristics.score': 1}}, 
    {$sort: { 'characteristics.score': 1 }}, 
    {$limit: 10} 
]) 
  • добавить match сцену, чтобы избавиться от пользователей без атрибута funny (который может быть легко индексируются).
  • unwind и match снова, чтобы сохранить только определенную часть данных
  • сохранить только необходимые данные с project
  • sort на точный счет
  • и limit результаты.

Таким образом, вы можете использовать индекс для первого совпадения.

Как я понимаю, если характеристики интересующие вас о не слишком много, ИМО было бы лучше, чтобы иметь структуру, как

{ 
    "name": "Joey", 
    "shy": 0.8 
    "funny": 0.6 
    "loving": 0.01 
} 

Таким образом, вы можете использовать индекс (разреженный или нет), чтобы сделать вашу жизнь проще!

+0

Точно, что я закончил делать :) спасибо за подтверждение этого. относительно второго предложения - к сожалению, существует слишком много разных «характеристик» для индексации (MongoDB в настоящее время позволяет до 64 различных индексов на коллекцию). – ozk

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