1. ホーム
  2. javascript

[解決済み] Mongoose を使って、mongodb から key-value map としてデータを取得する方法はありますか?

2022-02-07 21:47:34

質問

Mongodbコレクションに以下のデータがあります。

{_id: xxx1, fieldA: valueA_1, fieldB: valueB_1, fieldC: valueC_1},
{_id: xxx2, fieldA: valueA_1, fieldB: valueB_2, fieldC: valueC_2},
{_id: xxx3, fieldA: valueA_2, fieldB: valueB_3, fieldC: valueC_3},


このような構造を返すような Mongodb の集約演算子などはないでしょうか。

{
 "valueA_1": [
              {_id: xxx1, fieldA: valueA_1, fieldB: valueB_1, fieldC: valueC_1},
              {_id: xxx2, fieldA: valueA_1, fieldB: valueB_2, fieldC: valueC_2}
             ],

 "valueA_2": [
              {_id: xxx3, fieldA: valueA_2, fieldB: valueB_3, fieldC: valueC_3}
             ]
}

今は単純にSchema.find()をして、その後にreduce関数を結果に適用しています。

    data.reduce(function (map, obj) {
      map[obj.fieldA] = map[obj.fieldA] ? [...map[obj.fieldA], obj] : [obj];
      return map;
    }, {});

この動作をmongodbの演算子だけで実現するにはどうしたらいいか知りたいです。 また、reduce関数の代わりにこれらを使用した方がパフォーマンスが良いのかどうか。

皆さん、ありがとうございました。

解決方法は?

これを試してみてください

db.collection.aggregate([
  {
    $group: { // first group by the required fieldA
      _id: "$fieldA",
      docs: {
        $push: "$$ROOT"
      }
    }
  },
  {
    $group: { // this group to gather all documents in one array 'allDocsInOneArray' of objects
      // each object has a key = the value of fieldA, and a value = an array of the docs belong to this fieldA
      _id: null,
      allDocsInOneArray: {
        $push: {
          k: "$_id", // the key of the object (should be the value of fieldA, which is the _id now after the first group stage)
          v: "$docs" // an array of docs belong to this fieldA
          // the object should be in this format { k: '', v: [] } in order to be able to convert the whole array to another object in $arrayToObject operation
        }
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$arrayToObject": "$allDocsInOneArray"  // convert the array of objects to object with key = k (fieldA), value = v (its docs)
      }
    }
  }
])

できます テストはこちら

お役に立てれば幸いです。