Оптимизация запроса агрегации Монго с помощью условного поиска - PullRequest
1 голос
/ 18 марта 2019

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

событий

{
    "_id" : ObjectId("5c8f4d3bbbf999bd7d1cc11c"),
    "category" : "Comment",
    "reference_field" : ObjectId("5c8f4ba4bbf999bbb056984f"), // Object id of a document in the COMMENT collection
    "deleted_reference_field" : "Not Deleted",
    "summary" : "Some string"
},
{
    "_id" : ObjectId("5c8b7e6dbbf99995bdcb37ac"),
    "category" : "Comment",
    "reference_field" : ObjectId("5c8b3fe9bbf9997e1f18c816"), // object id of a document in the PROJECT collection
    "deleted_reference_field" : "Project",
    "summary" : "Here is a new comment!"
}

Итак, как вы можете видеть, обадокументы коллекции event ссылаются на разные коллекции.Это определяется атрибутом deleted_reference_field.

  • Если его значение равно Не удалено , тогда reference_field содержит объект, ссылающийся на коллекцию Comment.

  • Если значение Project или любая такая строка, то reference_field содержит идентификатор объекта коллекции, на которую он должен ссылаться.В этом примере это относится к коллекции Project.

Мне нужно выполнить $lookup для заполнения соответствующего reference_field.Для этого мне нужен какой-то оператор if-else, чтобы я мог указать, какую коллекцию я хочу просмотреть.

Псевдокод того, что должен делать мой конвейер агрегации:

Group all documents by Category
if reference_field is "Not Deleted"
then $lookup on Collection mentioned in Category
else $lookup on the deleted_reference_field Collection (Project in this case)

Текущий код агрегации: Мой текущий конвейер не эффективен.Я собираюсь, хотя N документы, каждый раз, когда у меня есть другая категория и другое значение deleted_reference_field.Выглядит это так:

db.events.aggregate([
    {
    "$facet": {
        "comments": [
            {"$match": {"category": "Comment"}},
            {"$match": {"deleted_reference_field": "Not Deleted"}},
            {
                "$lookup": {
                    "from": "comment",
                    "localField": "reference_field",
                    "foreignField": "_id",
                    "as": "Comments",
                }
            },
            {"$unwind": "$Comments"},
            {"$match": {"Comments.project_id": bson.ObjectId(project_id)}},
        ],
        "deleted_comments": [
            {"$match": {"category": "Comment"}},
            {"$match": {"deleted_reference_field": "Project"}},
            {"$match": {"reference_field": bson.ObjectId(project_id)}},
        ]}
    }

])

Как видите, есть 2 "корзины", один для комментариев и один для Удалено_входят .Поэтому каждый раз, когда я создаю сегмент, я просматриваю ВСЕ документы, чтобы отфильтровать документы с категорией «Комментарий» и deleted_reference_field как «Не удалено» или «Проект».Есть около 7-8 категорий (я показал только Комментарий), для которых я следовал тому же процессу, поэтому оказался очень неэффективным.

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

Вshort:

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

...