mongodb在两个对象之间添加键的值

huangapple go评论251阅读模式
英文:

mongodb add values of keys between two objects

问题

I want to create a matchmaking algo comparing two objects with each other. In detail I have to subtract each key of the objects, resulting in an output object with the subtracted values. However, the tricky part is that the keys might not be defined in one of the objects.

The objects, for example, can look like this:

{
  userMDs: {
    md1: 0.5,
    md2: 0.5,
    md3: 1,
    md7: -0.5,
    md8: 0.5,
    md9: 1,
    md13: -0.5,
    md14: 0.5,
    md15: 1,
    md19: -0.5,
    md20: -1,
    md21: 1,
    md25: -0.5,
    md26: 1
  },
  matchMDs: {
    md1: 0.5,
    md2: 0.5,
    md3: 1,
    md7: -0.5,
    md15: 1,
    md19: -0.5,
    md20: -1,
    md21: 1,
    md25: -0.5,
    md26: 1
  }
}

Identifying which keys are matching, I do this logic:

{
  $addFields: {
    commonKeys: {
      $filter: {
        input: { $objectToArray: "$userMDs" },
        as: "userMD",
        cond: { $in: ["$$userMD.k", { $map: { input: { $objectToArray: "$matchMDs" }, as: "matchMD", in: "$$matchMD.k" } }] }
      }
    }
  }
}

This results in a new object called "commonKeys," containing the matching keys. I am now having troubles doing the subtraction for the values of the keys that are existing in both objects.

Is there a way to look over each key of the commonKeys and access both the other objects for the subtraction?

Thanks in advance for any hint...!

英文:

I want to create a matchmaking algo comparing two objects with each other.
In detail I have to substract each key of the objects, resulting into an output object with the subtracted values. However the tricky part is that the keys might not be defined in one of the objects.

The objects e.g. can look like this:

{
  userMDs: {
    md1: 0.5,
    md2: 0.5,
    md3: 1,
    md7: -0.5,
    md8: 0.5,
    md9: 1,
    md13: -0.5,
    md14: 0.5,
    md15: 1,
    md19: -0.5,
    md20: -1,
    md21: 1,
    md25: -0.5,
    md26: 1
  },
	matchMDs: {
    md1: 0.5,
    md2: 0.5,
    md3: 1,
    md7: -0.5,
    md15: 1,
    md19: -0.5,
    md20: -1,
    md21: 1,
    md25: -0.5,
    md26: 1
  },
}

Identifying which keys are matching, I do this logic:

 {
    $addFields: {
      commonKeys: {
        $filter: {
          input: { $objectToArray: "$userMDs" },
          as: "userMD",
          cond: { $in: ["$$userMD.k", { $map: { input: { $objectToArray: "$matchMDs" }, as: "matchMD", in: "$$matchMD.k" } }] }
        }
      }
    }
  },

This results into a new object called "commonKeys", containing the matching keys.
I am now having troubles doing the substraction for the values of the keys that are existing in both objects.

Is there a way to look over each key of the commonKeys and access both the other objects for the substraction?

Thanks in advance for any hint...!

答案1

得分: 0

根据您想要的行为,以下是聚合操作的两个版本。

忽略缺失的键,仅减去存在的值

db.collection.aggregate([
  {
    $addFields: {
      commonKeys: {
        $filter: {
          input: {
            $objectToArray: "$userMDs"
          },
          as: "userMD",
          cond: {
            $in: [
              "$$userMD.k",
              {
                $map: {
                  input: {
                    $objectToArray: "$matchMDs"
                  },
                  as: "matchMD",
                  in: "$$matchMD.k"
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    $addFields: {
      subtracted: {
        $arrayToObject: {
          $map: {
            input: "$commonKeys",
            as: "common",
            in: {
              k: "$$common.k",
              v: {
                $round: [
                  {
                    $subtract: [
                      "$$common.v",
                      {
                        $ifNull: [
                          {
                            $arrayElemAt: [
                              {
                                $map: {
                                  input: {
                                    $filter: {
                                      input: {
                                        $objectToArray: "$matchMDs"
                                      },
                                      as: "item",
                                      cond: {
                                        $eq: [
                                          "$$item.k",
                                          "$$common.k"
                                        ]
                                      }
                                    }
                                  },
                                  as: "item",
                                  in: "$$item.v"
                                }
                              },
                              0
                            ]
                          },
                          0
                        ]
                      }
                    ]
                  },
                  1
                ]
              }
            }
          }
        }
      }
    }
  },
  {
    $project: {
      difference: "$subtracted"
    }
  }
])

MongoDB Playground Link,您可以在这里测试该聚合操作以确认它是否有效。

减去值,即使键缺失

db.collection.aggregate([
  {
    $addFields: {
      userMDsArr: {
        $objectToArray: "$userMDs"
      },
      matchMDsArr: {
        $objectToArray: "$matchMDs"
      }
    }
  },
  {
    $addFields: {
      subtracted: {
        $arrayToObject: {
          $map: {
            input: "$userMDsArr",
            as: "userMD",
            in: {
              k: "$$userMD.k",
              v: {
                $let: {
                  vars: {
                    matchMD: {
                      $arrayElemAt: [
                        {
                          $filter: {
                            input: "$matchMDsArr",
                            as: "matchMD",
                            cond: {
                              $eq: [
                                "$$matchMD.k",
                                "$$userMD.k"
                              ]
                            }
                          }
                        },
                        0
                      ]
                    }
                  },
                  in: {
                    $round: [
                      {
                        $subtract: [
                          "$$userMD.v",
                          {
                            $ifNull: [
                              "$$matchMD.v",
                              0
                            ]
                          }
                        ]
                      },
                      1
                    ]
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  {
    $project: {
      _id: 1,
      subtracted: 1
    }
  }
])

MongoDB Playground Link,您可以在这里测试该聚合操作以确认它是否有效。

英文:

Depending on the behaviour you want, here are the 2 versions of the aggregation.

Ignore missing keys, subtract only existing

db.collection.aggregate([
  {
    $addFields: {
      commonKeys: {
        $filter: {
          input: {
            $objectToArray: "$userMDs"
          },
          as: "userMD",
          cond: {
            $in: [
              "$$userMD.k",
              {
                $map: {
                  input: {
                    $objectToArray: "$matchMDs"
                  },
                  as: "matchMD",
                  in: "$$matchMD.k"
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    $addFields: {
      subtracted: {
        $arrayToObject: {
          $map: {
            input: "$commonKeys",
            as: "common",
            in: {
              k: "$$common.k",
              v: {
                $round: [
                  {
                    $subtract: [
                      "$$common.v",
                      {
                        $ifNull: [
                          {
                            $arrayElemAt: [
                              {
                                $map: {
                                  input: {
                                    $filter: {
                                      input: {
                                        $objectToArray: "$matchMDs"
                                      },
                                      as: "item",
                                      cond: {
                                        $eq: [
                                          "$$item.k",
                                          "$$common.k"
                                        ]
                                      }
                                    }
                                  },
                                  as: "item",
                                  in: "$$item.v"
                                }
                              },
                              0
                            ]
                          },
                          0
                        ]
                      }
                    ]
                  },
                  1
                ]
              }
            }
          }
        }
      }
    }
  },
  {
    $project: {
      difference: "$subtracted"
    }
  }
])

MongoDB Playground Link where you can test this aggregation to see that it works.

Subtract values even of missing keys

db.collection.aggregate([
  {
    $addFields: {
      userMDsArr: {
        $objectToArray: "$userMDs"
      },
      matchMDsArr: {
        $objectToArray: "$matchMDs"
      }
    }
  },
  {
    $addFields: {
      subtracted: {
        $arrayToObject: {
          $map: {
            input: "$userMDsArr",
            as: "userMD",
            in: {
              k: "$$userMD.k",
              v: {
                $let: {
                  vars: {
                    matchMD: {
                      $arrayElemAt: [
                        {
                          $filter: {
                            input: "$matchMDsArr",
                            as: "matchMD",
                            cond: {
                              $eq: [
                                "$$matchMD.k",
                                "$$userMD.k"
                              ]
                            }
                          }
                        },
                        0
                      ]
                    },
                    
                  },
                  in: {
                    $round: [
                      {
                        $subtract: [
                          "$$userMD.v",
                          {
                            $ifNull: [
                              "$$matchMD.v",
                              0
                            ]
                          }
                        ]
                      },
                      1
                    ]
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  {
    $project: {
      _id: 1,
      subtracted: 1
    }
  }
])

MongoDB Playground Link where you can test this aggregation to see that it works.

huangapple
  • 本文由 发表于 2023年7月3日 05:07:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76600810.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定