sql >> Database >  >> NoSQL >> MongoDB

Opzoeken met array van objecten

Je moet in principe $unwind eerst de array. MongoDB kan nog niet werken met de eigenschap "inner" van een object in een array als bron voor $lookup .

Ook voor efficiëntie moeten we echt $concatArrays gebruiken eerst om "aan te sluiten" bij de arraybron, en doe dan slechts één $lookup bediening:

Project.aggregate([
  { "$match": { "project_id": projectId} },
  { "$project": {
    "project_id": 1,
    "updated_at": 1,
    "created_at": 1,
    "owner": 1,
    "name": 1,
    "combined": {
      "$concatArrays": [
        { "$map": {
          "input": {
            "$filter": {
              "input": "$uploaded_files",
              "as": "uf",
              "cond": { "$eq": ["$$uf.upload_id", uploadId ] }
            }
          },
          "as": "uf",
          "in": {
            "$arrayToObject": {
              "$concatArrays": [
                { "$objectToArray": "$$uf" },
                [{ "k": "type", "v": "uploaded_files" }]
              ]
            }
          }
        }},
        { "$map": {
          "input": {
            "$filter": {
              "input": "$file_history",
              "as": "fh",
              "cond": { "$eq": ["$$fh.upload_id", uploadId ] }
            }
          },
          "as": "fh",
          "in": {
            "$arrayToObject": {
              "$concatArrays": [
                { "$objectToArray": "$$fh" },
                [{ "k": "type", "v": "file_history" }]
              ]
            }
          }
        }}
      ]
    }
  }},
  { "$unwind": "$combined" },
  { "$lookup": {
    "from": "files",
    "localField": "combined.file",
    "foreignField": "_id",
    "as": "combined.file"
  }},
  { "$unwind": "$combined.file" },
  { "$lookup": {
    "from": "users",
    "localField": "owner",
    "foreignField": "_id",
    "as": "owner"
  }},
  { "$unwind": "$owner" },
  { "$group": {
    "_id": "$_id",
    "project_id": { "$first": "$project_id" },
    "updated_at": { "$first": "$updated_at" },
    "created_at": { "$first": "$created_at" },
    "owner": { "$first": "$owner" },
    "name": { "$first": "$name" },
    "combined": { "$push": "$combined" }
  }},
  { "$project": {
    "project_id": 1,
    "updated_at": 1,
    "created_at": 1,
    "owner": 1,
    "name": 1,
    "uploaded_files": {
      "$filter": {
        "input": "$combined",
        "as": "cf",
        "cond": { "$eq": [ "$$cf.type", "uploaded_files" ] }
      }    
    },
    "file_history": {
      "$filter": {
        "input": "$combined",
        "as": "cf",
        "cond": { "$eq": [ "$$cf.type", "file_history" ] }
      }    
    }
  }}
])

In een notendop

  1. Breng de twee arrays samen op de bron en tag ze, dan $unwind eerst

  2. Doe de $lookup op het gecombineerde detail en $unwind dat

  3. Doe de $lookup op de andere buitenlandse bron en $unwind dat

  4. $group het document weer samen met een enkele array.

  5. $filter door het veld "tagnamen" of "type" dat we hebben toegevoegd om de arrays te "scheiden".

Je kunt hetzelfde soort proces volgen door gewoon $unwind te gebruiken op elke array, doe vervolgens de "join" en groepeer weer bij elkaar. Maar daar zijn echt veel meer stappen voor nodig dan simpelweg "combineren" in de eerste plaats.




  1. Is er een manier om het datumtype op te slaan als lokale tijd in MongoDB?

  2. Een array van arrays opvragen in MongoDB

  3. Hoe selecteer je alle records uit een mongodb-verzameling in golang met mgo

  4. Query in een MongoDB Map Reduce-functie