Ich führe eine Suchabfrage mit $ unwind aus, um alle Array-Elementergebnisse aus einem Array-Feld einer Sammlung zu finden, das mit einer anderen Sammlung verbunden ist. Ich benutze die folgende Abfrage:

db.getCollection('Products').aggregate([{$unwind:"$SupplierOffers"},{$lookup:{from:"Offers", localField:"SupplierOffers",foreignField:"_id", as:"Producttypes"}},
{$project:{"Producttypes.offeringType":1, _id:1}}])

Die tatsächlichen Ergebnisse sind

{
    "_id" : ObjectId("5bfe8978192b5c14e8d88ba7"),
    "Producttypes" : [ 
        {
            "offeringType" : "package A"
        }
    ]
}

{
    "_id" : ObjectId("5bfe8978192b5c14e8d88ba7"),
    "Producttypes" : [ 
        {
            "offeringType" : "package B"
        }
    ]
}

Ist es aufgrund der Annotation zum Abwickeln möglich, dass ich ein Ergebnis wie das folgende habe:

{
    "_id" : ObjectId("5bfe8978192b5c14e8d88ba7"),
    "Producttypes" : [ 
        {
            "offeringType" : ["package A","package B"]
        }
    ]
}

Ich nehme an, dies bezieht sich auf eine Gruppe oder ist aufgrund von Abwicklung nicht möglich. Ich brauche dies auf diese Weise, damit ich es weiter in Meteor umwandeln kann.

0
user2829319 18 Jän. 2019 im 18:29

3 Antworten

Beste Antwort

Sie haben Recht, dass Sie nach einer Gruppe suchen.

Versuchen Sie, dies Ihrer Pipeline hinzuzufügen

{
  $group: {
    _id: '_id',
    offeringType: { $addToSet: '$Producttypes.offeringType' }
  }
}

Bearbeiten: Hier ist die letzte Abfrage aus den Kommentaren für die Nachwelt:

db.getCollection("Products").aggregate([
  {
    $unwind: "$SupplierOffers"
  },
  {
    $lookup: {
      from: "Offers",
      localField: "SupplierOffers",
      foreignField: "_id",
      as: "Producttypes"
    }
  },
  {
    $group: {
      _id: "$_id",
      offeringType: { $addToSet: "$Producttypes.offeringType" }
    }
  },
  { $sort: { _id: 1 } }
]);

1
elhil 22 Jän. 2019 im 15:43

Dies stellt sich als einfacher heraus, wenn Sie nicht zuerst $unwind die Originaldokumente erstellen. $lookup kann direkt von einem Array von "Fremdschlüsseln" nachschlagen. Das Ergebnis ist dann bereits ein Array, sodass keine weiteren $unwind und $group mehr erforderlich sind.

db.getCollection('Products').aggregate([
    { $lookup: {
        from:"Offers",        
        localField:"SupplierOffers", 
        foreignField:"_id", 
        as:"Producttypes" 
    }}
])

Wenn Sie die Produkttypen so transformieren möchten, dass nur das Feld "Angebotsart" darin enthalten ist, können Sie optional { $addFields: {Producttypes: '$Producttypes.offeringType' } } } hinzufügen.

1
Asya Kamsky 22 Jän. 2019 im 16:16

Ich bin damit einverstanden, dass die Aggregation eine großartige und wesentliche Funktionalität ist, aber manchmal ist es schwierig, kleine, aber spezifische Änderungen zu kontrollieren.

Daher empfehle ich in Meteor.js, dass "this.added" wie unten eine der guten Lösungen ohne Aggregation sein könnte.

# Writing in Coffeescript
Meteor.publish 'pubName' ->
  cursor = Products.find()
  cursor.forEach (product) => #fat arrow for this binding
    #Play anything with product and the other collection's data
    product.Producttypes = Offers.findOne(_id: product.SupplierOffers)
    this.added('pubName', product._id, product) #The data binded to Products could be use in client
  return [
    cursor
    OtherCollection.find() #other collections to subscribe
  ]

Hoffe dazu könnte hilfreich sein.

0
jungwon jin 25 März 2020 im 19:40