Поиск по массиву идентификаторов mongodb

#mongodb #aggregation-framework #doctrine-odm

#mongodb #платформа агрегации #doctrine-odm

Вопрос:

Я сделал несколько поисковых запросов перед публикацией, но в настоящее время я столкнулся с проблемой. Я работаю с Mongo 4 с Symfony4 и Mongo-odm. Мне нужно исправить мой запрос оболочки, тогда я адаптирую его к doctrine-odm.

У меня есть две подобные коллекции :

схема :

 {
    "_id" : "5c6e6f7be05bd900a1682582",
    "name" : "Awesome name",
    "startDate" : ISODate("2019-02-13T05:48:24.000Z"),
    "endDate" : ISODate("2019-02-13T12:30:50.000Z"),
    "state" : "closed",
    "type" : "I",
    "agency" : "5c6cfe7ae05bd9007477f7ee",
    "drivers" : [ 
        "5c6cfe99e05bd90074783c99",
        "5c6cfe99e05bd90074784d85",
    ],
    "exportedAt" : ISODate("2019-02-13T12:32:02.000Z"),
    "createdAt" : ISODate("2019-02-21T09:29:31.783Z"),
    "updatedAt" : ISODate("2019-02-21T09:29:31.783Z"),
    "messages" : [
        "5c6e7125e05bd900a1683595", 
        "5c6e7125e05bd900a1683596", 
        "5c6e7125e05bd900a1683597", 
        "5c6e7126e05bd900a1683598"
    ],
    "orders" : [
        "5c6d0269e05bd900747a559c", 
        "5c6d0269e05bd900747a559c", 
        "5c6d0269e05bd900747a559c"
    ]
}
  

порядок :

 {
    "_id" : "5c6d04a9e05bd900747a7c40",
    "startDate" : ISODate("2019-02-19T08:35:04.000Z"),
    "endDate" : ISODate("2019-02-19T12:53:50.000Z"),
    "state" : "closed",
    "company" : 1982,
    "weight" : 960.0,
    "type" : "E",
    "circuit" : "5c6d0307e05bd900747a6c39",
    "agency" : "5c6cfe79e05bd9007477f580",
    "client" : "5c6d0074e05bd9007479a7c1",
    "createdAt" : ISODate("2019-02-20T19:45:54.392Z"),
    "updatedAt" : ISODate("2019-02-20T19:45:54.392Z"),
}
  

Из схемы я хочу получить документы заказов вместо их идентификатора.

Я пробовал запрашивать подобным образом :

 db.circuit.aggregate([ 
    { "$match": 
        { "agency": 
            { "$in": 
                [ 
                    "5c6cfe79e05bd9007477f559", "5c6cfe79e05bd9007477f55b", "5c6cfe79e05bd9007477f562", "5c6cfe79e05bd9007477f563", "5c6cfe79e05bd9007477f565", 
                    "5c6cfe79e05bd9007477f566", "5c6cfe79e05bd9007477f57e", "5c6cfe79e05bd9007477f57f", "5c6cfe79e05bd9007477f580", "5c6cfe79e05bd9007477f582", 
                    "5c6cfe79e05bd9007477f587", "5c6cfe79e05bd9007477f588", "5c6cfe79e05bd9007477f589", "5c6cfe79e05bd9007477f58a", "5c6cfe79e05bd9007477f590", 
                    "5c6cfe79e05bd9007477f591", "5c6cfe79e05bd9007477f592", "5c6cfe79e05bd9007477f593", "5c6cfe79e05bd9007477f594", "5c6cfe79e05bd9007477f595", 
                    "5c6cfe79e05bd9007477f596", "5c6cfe79e05bd9007477f59b", "5c6cfe79e05bd9007477f59c", "5c6cfe79e05bd9007477f5af", "5c6cfe79e05bd9007477f5b2", 
                    "5c6cfe79e05bd9007477f5e5", "5c6cfe79e05bd9007477f66d", "5c6cfe79e05bd9007477f679" 
                ] 
            }
        } 
    },
    {
        "$lookup": 
            {
                "from": "agency",
                "localField": "agency",
                "foreignField": "_id",
                "as": "agency"
            }
    },
    {"$unwind": "$agency"},
    {
        "$lookup": 
            {
                "from": "order",
                "localField": "orders",
                "foreignField": "_id",
                "as": "sub_orders"
            }
    },
    {
        $unwind: {
            path: "$sub_orders",
            preserveNullAndEmptyArrays: true
        }
    },
    {
        "$project": 
            {
                "name": "$$ROOT.nom",
                "startDate": "$$ROOT.startDate",
                "endDate": "$$ROOT.endDate",
                "state": "$$ROOT.state",
                "type": "$$ROOT.type",
                "agencyName": "$agency.name",
                "sub_orders": "$sub_orders"
            }
    }
]);
  

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

 {
    "_id" : "5c6e6f9ee05bd900a168268f",
    "name" : "Circuit",
    "startDate" : ISODate("2019-02-13T06:18:28.000Z"),
    "endDate" : ISODate("2019-02-13T11:40:12.000Z"),
    "state" : "closed",
    "type" : "I",
    "agencyName" : "Amazing Agency",
    "sub_orders" : {
        "_id" : "5c6d04a9e05bd900747a7c40",
        "startDate" : ISODate("2019-02-19T08:35:04.000Z"),
        "endDate" : ISODate("2019-02-19T12:53:50.000Z"),
        "state" : "closed",
        "company" : 1982,
        "weight" : 960.0,
        "type" : "E",
        "circuit" : "5c6d0307e05bd900747a6c39",
        "agency" : "5c6cfe79e05bd9007477f580",
        "client" : "5c6d0074e05bd9007479a7c1",
        "createdAt" : ISODate("2019-02-20T19:45:54.392Z"),
        "updatedAt" : ISODate("2019-02-20T19:45:54.392Z"),
    }
}
  

Однако я хочу получить столько документов заказа, сколько идентификаторов в массиве идентификаторов, таких как :

 {
    "_id" : "5c6e6f9ee05bd900a168268f",
    "name" : "Circuit",
    "startDate" : ISODate("2019-02-13T06:18:28.000Z"),
    "endDate" : ISODate("2019-02-13T11:40:12.000Z"),
    "state" : "closed",
    "type" : "I",
    "agencyName" : "Amazing Agency",
    "sub_orders" : {
        "_id" : "5c6d04a9e05bd900747a7c40",
        "startDate" : ISODate("2019-02-19T08:35:04.000Z"),
        "endDate" : ISODate("2019-02-19T12:53:50.000Z"),
        "state" : "closed",
        "company" : 1982,
        "weight" : 960.0,
        "type" : "E",
        "createdAt" : ISODate("2019-02-20T19:45:54.392Z"),
        "updatedAt" : ISODate("2019-02-20T19:45:54.392Z"),
    },{
        "_id" : ".....",
        "startDate" : ISODate("2019-02-19T08:35:04.000Z"),
        "endDate" : ISODate("2019-02-19T12:53:50.000Z"),
        "state" : "closed",
        "company" : 1982,
        "weight" : 960.0,
        "type" : "E",
        "createdAt" : ISODate("2019-02-20T19:45:54.392Z"),
        "updatedAt" : ISODate("2019-02-20T19:45:54.392Z"),
    },{
        "_id" : ".....",
        "startDate" : ISODate("2019-02-19T08:35:04.000Z"),
        "endDate" : ISODate("2019-02-19T12:53:50.000Z"),
        "state" : "closed",
        "company" : 1982,
        "weight" : 960.0,
        "type" : "E",
        "createdAt" : ISODate("2019-02-20T19:45:54.392Z"),
        "updatedAt" : ISODate("2019-02-20T19:45:54.392Z"),
    }
}
  

Спасибо, что спасли меня! 🙂

Комментарии:

1. Привет, кажется, что $ lookup выполняет addToSet для размещения элементов в массиве, но не может найти никакой информации в документе. Попробуйте использовать разные orders _id в вашем документе схемы, вы увидите несколько заказов в результате sub_orders.

2. Спасибо за ответ, я пробовал со многими другими идентификаторами и ссылался на коллекции, такие как драйверы, но то же самое.

Ответ №1:

Мне удалось сделать то, что я хотел, со следующим запросом, это занимает у меня несколько часов … 🙂

 db.circuit.aggregate([ 
    { "$match": 
        { "agency": 
            { "$in": 
                [ 
"5c6cfe79e05bd9007477f559", "5c6cfe79e05bd9007477f55b", "5c6cfe79e05bd9007477f562", "5c6cfe79e05bd9007477f563", "5c6cfe79e05bd9007477f565", 
                    "5c6cfe79e05bd9007477f566", "5c6cfe79e05bd9007477f57e", "5c6cfe79e05bd9007477f57f", "5c6cfe79e05bd9007477f580", "5c6cfe79e05bd9007477f582", 
                    "5c6cfe79e05bd9007477f587", "5c6cfe79e05bd9007477f588", "5c6cfe79e05bd9007477f589", "5c6cfe79e05bd9007477f58a", "5c6cfe79e05bd9007477f590", 
                    "5c6cfe79e05bd9007477f591", "5c6cfe79e05bd9007477f592", "5c6cfe79e05bd9007477f593", "5c6cfe79e05bd9007477f594", "5c6cfe79e05bd9007477f595", 
                    "5c6cfe79e05bd9007477f596", "5c6cfe79e05bd9007477f59b", "5c6cfe79e05bd9007477f59c", "5c6cfe79e05bd9007477f5af", "5c6cfe79e05bd9007477f5b2", 
                    "5c6cfe79e05bd9007477f5e5", "5c6cfe79e05bd9007477f66d", "5c6cfe79e05bd9007477f679" 
                ] 
            }
        },
    },
    {
        "$match": 
       { "date": { "$lte": ISODate("2019-02-13T12:32:02.000Z") } }
    },
    {"$match": 
       { "date": { "$gte": ISODate("2019-02-11T12:32:02.000Z") } } 
    },
    {
        "$lookup": 
            {
                "from": "agency",
                "localField": "agency",
                "foreignField": "_id",
                "as": "agency"
            }
    },
    {"$unwind": "$agency"},
    {
        "$lookup": 
            {
                "from": "order",
                "localField": "orders",
                "foreignField": "_id",
                "as": "orders"
            }
    },
    { "$unwind": "$orders" },
    {
        "$lookup": 
            {
                "from": "driver",
                "localField": "drivers",
                "foreignField": "_id",
                "as": "drivers"
            }
    },
    { "$unwind": "$drivers" },
    { "$unwind": "$camions" },
    {
        "$group": {
            "_id": "$_id",
            "orders": { "$addToSet": "$orders" },
            "drivers": { "$last": "$drivers" },
            "agency": { "$addToSet": "$agency" },
            "type": { "$addToSet": "$type" },
            "state": { "$addToSet": "$state" },
            "date": { "$addToSet": "$date" }
        }
    },
    { "$unwind": "$agency" },
    { "$unwind": "$date" },
    { "$unwind": "$type" },
    { "$unwind": "$state" }
    {
        "$project": 
            {
                "unloaded_orders": {
                    $filter: { 
                        input: '$orders',
                        as: 'o',
                        cond: { $eq: ['$$o.state', 'unloaded'] }
                    }
                },
                "unclosed_orders": {
                    $filter: { 
                        input: '$orders',
                        as: 'o',
                        cond: { $in: ['$$o.state', ['added', 'edited', 'started']] }
                    }
                },
                "closed_orders": {
                    $filter: { 
                        input: '$orders',
                        as: 'o',
                        cond: { $eq: ['$$o.state', 'closed'] }
                    }
                },
                "agency": "$agency",
                "date": "$date",
                "state": "$state",
                "type": "$type",
                "drivers": "$drivers"
            }
    }
]);
  

Надеюсь, это могло бы кому-то помочь 🙂

Комментарии:

1. Было ли это необходимо с doctrine-odm? Если вы правильно аннотируете (или сопоставляете) свои ссылки, doctrine-odm правильно увлажнит ваши классы. Выполнение $circuit->getOrders(); автоматически выполнит агрегацию, чтобы вернуть массив Orders документов, которые связаны с Circuit $cricuit .