sql >> Databasteknik >  >> NoSQL >> MongoDB

C# Mongodb kartesisk produkt av dokument med flera objektmatriser

Du kan prova nedanstående aggregeringspipeline.

Notera mergeObjects aggregeringsoperator är tillgänglig i 3.5.6 + utvecklingsversion som kommer att rullas in i kommande 3.6 släpp.

db.collection.find();
{
 "data" : [
  [
   {
    "movie" : "starwars",
    "showday" : "monday"
   },
   {
    "movie" : "batman",
    "showday" : "thursday"
   },
   {
    "movie" : "sleepless",
    "showday" : "tuesday"
   }
  ],
  [
   {
    "actor" : "angelina",
    "location" : "new york"
   },
   {
    "actor" : "jamie",
    "location" : "california"
   },
   {
    "actor" : "mcavoy",
    "location" : "arizona"
   }
  ]
 ]
}

Aggregation med villkorligt uttryck.

aggregate({
 $project: {
  cp: {
   $reduce: {
    input: "$data",
    initialValue: {
     $arrayElemAt: ["$data", 0] // Set the initial value to the first element of the arrays.
    },
    in: {
     $let: {
      vars: {
       currentr: "$$this", // Current processing element
       currenta: "$$value" // Current accumulated value 
      },
      in: {
       $cond: [{ // Conditional expression to return the accumulated value as initial value for first element
        $eq: ["$$currentr", "$$currenta"]
       },
       "$$currenta",
       { // From second element onwards prepare the cartesian product
        $reduce: {
         input: {
          $map: {
           input: "$$currenta",
           as: a"a",
           in: {
            $map: {
             input: "$$currentr",
             as: r"r",
             in: {
              $mergeObjects: ["$$a", "$$r"] // Merge accumulated value with the current processing element
             }
            }
           }
          }
         },
         initialValue: [],
         in: {
         $concatArrays: ["$$value", "$$this"] // Reduce the merged values which will be used as accumulator for next element
         }
        }
       }]
      }
     }
    }
   }
  }
 }
});

Aggregation( med $setUnion ).

Denna lösning lades endast till för att undertrycka det villkorliga uttrycket för att ge en mer läsbar pipeline.

aggregate({
 $project: {
  cp: {
   $reduce: {
    input: "$data",
    initialValue: {
     $arrayElemAt: ["$data", 0] // Set the initial value to the first element of the arrays.
    },
    in: {
     $let: {
      vars: {
       currentr: "$$this", // Current processing element
       currenta: "$$value" // Current accumulated value 
      },
      in:{ 
       $reduce: {
        input: {
         $map: {
          input: "$$currenta",
          as: "a",
          in: {
           $map: {
            input: "$$currentr",
            as: "r",
            in: {
             $mergeObjects: ["$$a", "$$r"] // Merge accumulated value with the current processing element
            }
           }
          }
         }
        },
        initialValue: [],
        in: {
         $setUnion: ["$$value", "$$this"] // Reduce the merged values which will be used as accumulator for next element
        }
       }
      }
     }
    }
   }
  }
 }
});

Uppdatera

Båda ovanstående lösningar kommer inte att fungera med att upprepa värden över arrayer som noterats av Asya Kamskys kommentarer nedan på grund av den felaktiga $cond i den första lösningen och $setUnion i andra lösningen.

Den korrekta korrigeringen är att

börja med initialValue av [ { } ]

Eller

ändra input för att utesluta det första elementet som input: {$slice:["$data", 1, {$subtract:[{$size:"$data"},1]}]},

Komplett aggregeringspipeline

aggregate({
 $project: {
  cp: {
   $reduce: {
    input: {$slice:["$data", 1, {$subtract:[{$size:"$data"},1]}]},
    initialValue: {$arrayElemAt:["$data",0]},
    in: {
     $let: {
      vars: {
       currentr: "$$this", 
       currenta: "$$value" 
      },
      in:{ 
       $reduce: {
        input: {
         $map: {
          input: "$$currenta",
          as: "a",
          in: {
           $map: {
            input: "$$currentr",
            as: "r",
            in: {
             $mergeObjects: ["$$a", "$$r"] 
            }
           }
          }
         }
        },
        initialValue: [],
        in: {
         $concatArrays: ["$$value", "$$this"] 
        }
       }
      }
     }
    }
   }
  }
 }
});

Referens:Kartesisk produkt av flera arrayer i JavaScript




  1. Implementering av paginering i mongodb

  2. Kunde inte ansluta till Redis på 127.0.0.1:6379:Anslutning nekades med hembryggning

  3. Hur man gör korrekt databastestning (TDD) på Rails 3 med MongoDB och Mongoid

  4. Det bästa sättet att vara värd för MongoDB på DigitalOcean