Совпадение двух одинаковых полей массивов одинаковых документов без $ unwind - PullRequest
0 голосов
/ 04 ноября 2018

у меня ниже workouts коллекция

[
  {
    "receiverWorkout": {
      "exercises": [
        { "_id": "1", "reps": 0 },
        { "_id": "2", "reps": 4 }
      ]
    },
    "senderWorkout": {
      "exercises": [
        { "_id": "2", "reps": 12 },
        { "_id": "1", "reps": 8 }
      ]
    }
  }
]

Мне нужно сопоставить те же _id из receiverWorkout и senderWorkout упражнений и я хочу добавить ключ won true или false , чьи reps больше .

Если вы видите, что первый элемент receiverWorkout упражнений ({ "_id": "1", "reps": 0 }) совпадает со вторым элементом senderWorkout упражнений ({ "_id": "1", "reps": 8 }), потому что оба имеют одинаковые _id

Ожидаемый результат должен быть примерно таким:

[
  {
    "receiverWorkout": {
      "exercises": [
        { "_id": "1", "reps": 0, "won": false },
        { "_id": "2", "reps": 4, "won": false }
      ]
    },
    "senderWorkout": {
      "exercises": [
        { "_id": "2", "reps": 12, "won": true },
        { "_id": "1", "reps": 8, "won": true }
      ]
    }
  }
]

Я хочу избежать $unwind

Пожалуйста, помогите !!!

Ответы [ 2 ]

0 голосов
/ 04 ноября 2018

Вы можете использовать ниже агрегации.

Один проход

db.colname.aggregate([
 {"$project":{
  "exercises":{
   "$reduce":{
    "input":"$receiverWorkout.exercises",
    "initialValue":{"receiverWorkout":[],"senderWorkout":[]},
    "in":{"$let":{
     "vars":{
      "sen":{"$arrayElemAt":["$senderWorkout.exercises",{"$indexOfArray":["$senderWorkout.exercises._id","$$this._id"]}]}
     },
     "in":{
      "receiverWorkout":{
       "$concatArrays":[
        "$$value.receiverWorkout",
        [{"_id":"$$this._id","reps":"$$this.reps","won":{"$gt":["$$this.reps","$$sen.reps"]}}]
       ]
      },
      "senderWorkout":{
       "$concatArrays":[
        "$$value.senderWorkout",
        [{"_id":"$$sen._id","reps":"$$sen.reps","won":{"$gt":["$$sen.reps","$$this.reps"]}}]
       ]
      }
     }
    }}
   }
  }
 }},
 {"$project":{
  "receiverWorkout.exercises":"$exercises.receiverWorkout",
  "senderWorkout.exercises":"$exercises.senderWorkout"
 }}
])

Без использования $unwind

db.colname.aggregate(
{"$project":{
  "receiverWorkout.exercises":{
    "$map":{
      "input":"$receiverWorkout.exercises",
      "in":{
        "$let":{
          "vars":{"sen":{"$arrayElemAt":["$senderWorkout.exercises",{"$indexOfArray":["$senderWorkout.exercises._id","$$this._id"]}]}},
          "in":{
            "_id":"$$this._id",
            "reps":"$$this.reps",
            "won":{"$gt":["$$this.reps","$$sen.reps"]}
          }
        }
      }
    }
  },
  "senderWorkout.exercises":{
    "$map":{
      "input":"$senderWorkout.exercises",
      "in":{
        "$let":{
          "vars":{"rec":{"$arrayElemAt":["$receiverWorkout.exercises",{"$indexOfArray":["$receiverWorkout.exercises._id","$$this._id"]}]}},
          "in":{
            "_id":"$$this._id",
            "reps":"$$this.reps",
            "won":{"$gt":["$$this.reps","$$rec.reps"]}
          }
        }
      }
    }
  }
}})

С $unwind

db.colname.aggregate([
  {"$unwind":"$senderWorkout.exercises"},
  {"$unwind":"$receiverWorkout.exercises"},
  {"$sort":{"receiverWorkout.exercises._id":1,"senderWorkout.exercises._id":1}},
  {"$addFields":{
    "receiverWorkout.exercises.won":{
      "$cond":[
        {"$gt":["$receiverWorkout.exercises.reps","$senderWorkout.exercises.reps"]},
        true,
        false
      ]
    },
    "senderWorkout.exercises.won":{
      "$cond":[
        {"$gt":["$receiverWorkout.exercises.reps","$senderWorkout.exercises.reps"]},
        false,
        true
      ]
    }
  }},
  {"$group":{
    "_id":"$_id",
    "receiverWorkout":{"$addToSet":"$receiverWorkout.exercises"},
    "senderWorkout":{"$addToSet":"$senderWorkout.exercises"}
  }}
])
0 голосов
/ 04 ноября 2018

Вам не нужно использовать индекс массива для достижения этой цели. Если я хорошо понимаю, вам нужно знать, для каждой записи в вашем массиве senderWorkout.exercises, присутствует ли элемент с таким же _id в массиве receiverWorkout.exercises. Вот способ сделать это:

db.collection.aggregate([
  {
    $addFields: {
      "senderWorkout.exercises": {
        $map: {
          input: "$senderWorkout.exercises",
          as: "ex",
          in: {
            $cond: {
              if: {
                $in: [
                  "$$ex._id",
                  "$receiverWorkout.exercises._id"
                ]
              },
              then: {
                _id: "$$ex._id",
                reps: "$$ex.reps",
                result: true
              },
              else: {
                _id: "$$ex._id",
                reps: "$$ex.reps",
                result: false
              }
            }
          }
        }
      }
    }
  }
])

Вы можете попробовать здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...