Search code examples
mongodbspring-data-mongodbmongodb-compass

MongoDb Compass export db ref as embedded JSON


Is there a way to export a collection with all DBRef Objects embedded in a single JSON?

I tried to export the collection from compass, but it does not resolve the dbrefs to embedded json.


Example of the data structures:

Process:

{
    "_id": {
        "$oid": "5f44e89aa1f4c77447629a29"
    },
    "name": "test process",
    "description": "A test configuration for a process",
    "milestones": [{
        "$ref": "milestone",
        "$id": {
            "$oid": "5f5753636b75033a49b7cc7b"
        }
    }, {
        "$ref": "milestone",
        "$id": {
            "$oid": "5f5753636b75033a49b7cc82"
        }
    }]
}

Milestones:

[{
  "_id": {
    "$oid": "5f5753636b75033a49b7cc7b"
  },
  "name": "S1",
  "order": 0,
  "results": [
    {
      "$ref": "resultDefinition",
      "$id": {
        "$oid": "5f5753636b75033a49b7cc79"
      }
    },
    {
      "$ref": "resultDefinition",
      "$id": {
        "$oid": "5f5753636b75033a49b7cc7a"
      }
    }
  ]
},{
  "_id": {
    "$oid": "5f5753636b75033a49b7cc82"
  },
  "name": "S2",
  "order": 1,
  "results": [
    {
      "$ref": "resultDefinition",
      "$id": {
        "$oid": "5f5753636b75033a49b7cc7d"
      }
    },
    {
      "$ref": "resultDefinition",
      "$id": {
        "$oid": "5f5753636b75033a49b7cc7e"
      }
    },
    {
      "$ref": "resultDefinition",
      "$id": {
        "$oid": "5f5753636b75033a49b7cc7f"
      }
    },
    {
      "$ref": "resultDefinition",
      "$id": {
        "$oid": "5f5753636b75033a49b7cc80"
      }
    },
    {
      "$ref": "resultDefinition",
      "$id": {
        "$oid": "5f5753636b75033a49b7cc81"
      }
    }
  ]
}]

Phases:

{
    "_id": {
        "$oid": "5f5753636b75033a49b7cc7c"
    },
    "name": "P1",
    "activityStream": {
        "$ref": "activityStream",
        "$id": {
            "$oid": "5f5755076b75033a49b7cc83"
        }
    }
}

ResultDefinitions:

[{
  "_id": {
    "$oid": "5f5753636b75033a49b7cc79"
  },
  "name": "userresult",
  "resultType": "User"
},{
  "_id": {
    "$oid": "5f5753636b75033a49b7cc7a"
  },
  "name": "planDateResult",
  "resultType": "PlanDate"
},{
  "_id": {
    "$oid": "5f5753636b75033a49b7cc7d"
  },
  "name": "fileResult",
  "resultType": "File"
},{
  "_id": {
    "$oid": "5f5753636b75033a49b7cc7e"
  },
  "name": "dateResult",
  "resultType": "Date"
},{
  "_id": {
    "$oid": "5f5753636b75033a49b7cc7f"
  },
  "name": "textresult",
  "resultType": "Text"
},{
  "_id": {
    "$oid": "5f5753636b75033a49b7cc80"
  },
  "name": "booleanResult",
  "resultType": "Boolean"
},{
  "_id": {
    "$oid": "5f5753636b75033a49b7cc81"
  },
  "name": "numberResult",
  "resultType": "Number"
}]

Relations:

Process can have n milestones. Milestone has one or no Phase. Phase has more nested paths, but not relevant for an example. Milestone can have n ResultDefinitions


Solution

  • You can make a aggregation query and use $out operator, this will copy query result in separate collection, you can modify your query as per your requirement, see the last stage is $out: <collection name>, just provide the name of collection and execute this query, this will copy result in that collection, and you can export that collectoin.

    db.process.aggregate([
      { $unwind: "$milestones" },
      {
        $lookup: {
          from: "milestone",
          let: { id: "$milestones.$id" },
          pipeline: [
            { $match: { $expr: { $eq: ["$$id", "$_id"] } } },
            { $unwind: "$results" },
            {
              $lookup: {
                from: "resultDefinition",
                localField: "results.$id",
                foreignField: "_id",
                as: "results"
              }
            },
            { $unwind: "$results" },
            {
              $group: {
                _id: "$_id",
                name: { $first: "$name" },
                order: { $first: "$order" },
                results: { $push: "$results" }
              }
            }
          ],
          as: "milestones"
        }
      },
      { $unwind: "$milestones" },
      {
        $group: {
          _id: "$_id",
          name: { $first: "$name" },
          description: { $first: "$description" },
          milestones: { $push: "$milestones" }
        }
      },
    
      // you can specify the name of collection that you want
      { $out: "collection name" }
    ])
    

    Playground