Агрегирование с поиском и контролем Strings в MongoDb - PullRequest
1 голос
/ 09 апреля 2020

У меня есть две коллекции событий & участников :

событий Схема:

{
   name : String,
   members: [{status : Number, memberId : {type: Schema.Types.ObjectId, ref: 'members'}]
}

Примеры событий Do c:

"_id" : ObjectId("5e8b0bac041a913bc608d69d")
  "members" : [ 
        {
            "status" : 4,
            "_id" : ObjectId("5e8b0bac041a913bc608d69e"),
            "memberId" : ObjectId("5e7dbf5b257e6b18a62f2da9"),
            "date" : ISODate("2020-04-06T10:59:56.997Z")
        }, 
        {
            "status" : 1,
            "_id" : ObjectId("5e8b0bf2041a913bc608d6a3"),
            "memberId" : ObjectId("5e7e2f048f80b46d786bfd67"),
            "date" : ISODate("2020-04-06T11:01:06.463Z")
        }
    ],

членов Схема:

{
  firstname : String
  photo  : String
} 

членов Пример Do c:

  [{
        "_id" : ObjectId("5e7dbf5b257e6b18a62f2da9"),
        "firstname" : "raed",
        "photo" : "/users/5e7dbf5b257e6b18a62f2da9/profile/profile-02b13aef6e.png"
    }, 
    {
        "_id" : ObjectId("5e7e2f048f80b46d786bfd67"),
        "firstname" : "sarra",
        "photo" : "/5e7e2f048f80b46d786bfd67/profile/profile-c79f91aa2e.png"
    }]

Я сделал запрос с агрегатом и поиском, чтобы получить заполненные данные членов, и я хочу объединить поля фотографий членов в строку, но я получаю ошибку, Как я могу сделать Конкат?

Запрос:

db.getCollection('events').aggregate([
        { $match: { _id: ObjectId("5e8b0bac041a913bc608d69d")}},
        {
            "$lookup": {
                "from": "members",
                "localField": "members.memberId",
                "foreignField": "_id",
                "as": "Members"
            }
        },
        {
            $project: {
                "Members.firstname" : 1,
                "Members.photo": 1,
                //"Members.photo": {$concat:["http://myurl", "$Members.photo"]},
                "Members._id" : 1,
                },

        }
    ])

Результат без конкат:

{
    "_id" : ObjectId("5e8b0bac041a913bc608d69d"),
    "Members" : [ 
        {
            "_id" : ObjectId("5e7dbf5b257e6b18a62f2da9"),
            "firstname" : "raed",
            "photo" : "/users/5e7dbf5b257e6b18a62f2da9/profile/profile-02b13aef6e.png"
        }, 
        {
            "_id" : ObjectId("5e7e2f048f80b46d786bfd67"),
            "firstname" : "sarra",
            "photo" : "/5e7e2f048f80b46d786bfd67/profile/profile-c79f91aa2e.png"
        }
    ]
}

Ошибка :

$concat only supports strings, not array

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

альтернатива использования pipeline в ответе выше

мы можем использовать project и group

db.events.aggregate([
    { 
        $match: { _id: ObjectId("5e8b0bac041a913bc608d69d") } 
    },
    {
        $unwind: '$members' // to spread the members array into a stream of documents
    },
    {
        $lookup: {
            from: "members",
            localField: "members.memberId",
            foreignField: "_id",
            as: "member"
        }
    },
    {
        $unwind: '$member' // each document will have array of only one member, so do this unwind to convert it to an object
    },
    {
        $project: { // do the project here to be able to use the $concat operator
            'member._id': 1,
            'member.firstname': 1,
            'member.photo': 1,
            'member.photo': { $concat: ['http://myurl', '$member.photo'] } // now we can use the $concat as member is an object, then member.photo exists
        }
    },
    {
        $group: { // do that grouping stage to gather all the members belong to the same document in one array again
            _id: '$_id',
            Members: {
                $addToSet: '$member'
            }
        }
    }

])
1 голос
/ 09 апреля 2020

Вы можете сделать это, просто добавив pipeline к $lookup stage

db.events.aggregate([
  {
    $match: {
      _id: ObjectId("5e8b0bac041a913bc608d69d"),
    },
  },
  {
    $lookup: {
      from: "members",
      let: { memberId: "$members.memberId" },
      pipeline: [
        { $match: { $expr: { $in: ["$_id", "$$memberId"] } } },
        {
          $project: {
            firstname: 1,
            photo: { $concat: ["http://myurl", "$photo"] }
          }
        }
      ],
      as: "Members",
    }
  },
  /** Optional */
  {$project : {Members: 1}}
]);

Тест: MongoDB-Playground

...