2017-01-24 5 views
0

Ich habe eine Tabellenstruktur wie unten angegeben.So erhalten Sie ein vorhandenes Dokument oder ein neu hinzugefügtes Dokument

{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6b8"), 
"product" : "product1", 
"title" : "Alt Summit 1", 
"category" : "category1", 
"order" : 1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6b9"), 
"product" : "product2", 
"title" : "Alt Summit 2", 
"category" : "category1", 
"order" : 2 
} 
    { 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6ba"), 
"product" : "product1", 
"title" : "Alt Summit 1", 
"category" : "category1", 
"order" : 2, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bb"), 
"product" : "product2", 
"title" : "Alt Summit 2", 
"category" : "category1", 
"order" : 1, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bc"), 
"product" : "product3", 
"title" : "Alt Summit 3", 
"category" : "category1", 
"order" : 3, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bd"), 
"product" : "product4", 
"title" : "Alt Summit 4", 
"category" : "category1", 
"order" : 4 
} 

Ich möchte zuerst die Datenbankstruktur erklären.

Ich habe Standardprodukte für jeden Benutzer auf meiner Website und Benutzer können ihre eigenen Produkte zur Liste hinzufügen oder sie können die bestehende Liste neu anordnen. Wenn sie ein neues Produkt hinzufügen, wird es durch ihren Benutzernamen hinzugefügt. Wenn sie die Produkte nachbestellen, bekomme ich die vorhandenen Standarddatensätze und füge sie ein, indem ich den Benutzernamen anhefte und die Reihenfolge ändere (das wirst du verstehen, wenn du die obigen Daten beobachtest).

Nun, wie kann ich die Produkte für eine benutzerspezifische Kategorie erhalten.

Zum Beispiel, wenn ich alle Produkte für einen Benutzer1 in Kategorie1 erhalten soll, sollte die Ausgabe wie folgt sein (sortiert nach dem Auftragsfeld). Wenn Sie die obigen Daten sorgfältig beobachten, wird das gleiche Produkt mit dem Zusatzfeld added_by wiederholt und die Reihenfolge geändert. Ich möchte die Reihenfolge des Benutzers erhalten, wenn der Benutzer es anpasst, wenn nicht die Standardreihenfolge.

{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bb"), 
"product" : "product2", 
"title" : "Alt Summit 2", 
"category" : "category1", 
"order" : 1, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6ba"), 
"product" : "product1", 
"title" : "Alt Summit 1", 
"category" : "category1", 
"order" : 2, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bc"), 
"product" : "product3", 
"title" : "Alt Summit 3", 
"category" : "category1", 
"order" : 3, 
"added_by" : user1 
} 
{ 
"_id" : ObjectId("5870f1d9dd0ef6e62102e6bd"), 
"product" : "product4", 
"title" : "Alt Summit 4", 
"category" : "category1", 
"order" : 4 
} 

Ich bin offen für jeden Vorschlag auf, wenn ich die Struktur der Tabelle ändern sollte. Aber zu jedem gegebenen Zeitpunkt sollte ich in der Lage sein, zu dem Ausgang zu gelangen, den ich oben erwähnt habe.

+0

'db.yourCollection.find ({ "Kategorie": "category1", "added_by": "user1"}). Sort ({ "order": 1})' sollten Sie den Cursor zurück, die Sie‘ suchend, nein? – Adam

+0

Nein @Adam Ich sollte immer noch die Standardprodukte erhalten, wenn der Benutzer die Objekte nicht neu geordnet hat. Die obige Abfrage gibt mir nur Benutzer hinzugefügt Produkte oder Benutzer nachbestellte Produkte. Wenn dasselbe Produkt in derselben Kategorie sowohl standardmäßig als auch von einem Benutzer hinzugefügt wird, sollte ich dann die Benutzerbestellung zusammen mit anderen Standardprodukten erhalten. – Shravya

+0

die Standardprodukte sind definiert als diejenigen, die keinen '" added_by "' Schlüssel haben? Wenn ja, dann versuche 'db.yourCollection.find ({" $ oder ": [{" category ":" category1 "," added_by ":" user1 "}, {" added_by ": {" $ exists ": false} }]}).sort ({"order": 1}) ' – Adam

Antwort

1

Sie können die folgende Aggregation mit der aktuellen Mongo 3.4-Version versuchen.

$match Dokumente für Abfragekriterien.

$group Dokumente auf product und wählen Sie die $first auf der Grundlage der früheren Sortierreihenfolge, während das Dokument mit $$ROOT zu halten.

$replaceRoot, um das root Dokument auf die höchste Ebene zu fördern.

'$ sort' von order Feld.

db.collection.aggregate([{ 
    $match: { 
    "category": "category1", 
     $or: [{ 
      "added_by": "user1" 
     }, { 
      "added_by": { 
       "$exists": false 
      } 
     }] 
    } 
}, { 
    $group: { 
     "_id": "$product", 
     "root": { 
      "$first": "$$ROOT" 
     } 
    } 
}, { 
    $replaceRoot: { 
     newRoot: "$root" 
    } 
},{ 
    $sort: { 
     "order": 1 
    } 
}]) 

Update nach OP Kommentar des

$group Dokumente auf product und $push alle Produkte mit $$ROOT.

$project Stufe des $size wenn nicht $eq zu 1 ist, dann $filter zu vergleichen, um ein Produkt mit dem added_by Feld zu holen.

db.collection.aggregate([{ 
    $match: { 
     "category": "category1", 
     $or: [{ 
      "added_by": "user1" 
     }, { 
      "added_by": { 
       "$exists": false 
      } 
     }] 
    } 
}, { 
    $group: { 
     "_id": "$product", 
     "products": { 
      "$push": "$$ROOT" 
     } 
    } 
}, { 
    $project: { 
     "_id": 0, 
     "product": { 
      "$arrayElemAt": [{ 
        "$cond": [ 
         { 
          $eq: [{$size: "$products"}, 1] 
         }, 
         "$products", 
         { 
          "$filter": { 
           input: "$products", 
           as: "product", 
           cond: { 
            $ifNull: ["$$product.added_by", false] 
           } 
          } 
         } 
        ] 
       }, 
       0 
      ] 
     } 
    } 
}, { 
    $replaceRoot: { 
     newRoot: "$product" 
    } 
}, { 
    $sort: { 
     "order": 1 
    } 
}]); 
+0

Danke für die Antwort @Veeram. Ich sehe, dass Sie das erste von zwei Dokumenten auswählen. Aber, gibt es irgendeine Weise, die ich ein Dokument wähle, das added_by Feld hat, anstatt das erste oder letzte Element auszuwählen. Ich denke, für die Struktur, die ich gepostet habe, funktioniert die Lösung, die du gegeben hast, immer noch gut. Ich werde es trotzdem überprüfen, aber es wäre großartig, wenn du mit der Änderung, die ich in diesem Kommentar erwähnt habe, updaten könntest. – Shravya

+0

Gern geschehen. Ich werde die Antwort aktualisieren, aber ich muss es nur ein bisschen mehr verstehen. Ich glaube ich habe einen Fehler gemacht und hätte das letzte Produkt auswählen sollen. Der Grund für die Auswahl der letzten war der Gedanke, dass Sie die Bestellung des Produkts nach der Bestellung des Standardprodukts erneut bestellen werden. Wenn ich also in der Pipeline sortiere, werde ich das Nachbestellprodukt zuletzt haben. Ist das nicht der Fall? Kann der Benutzer eine Bestellung aufgeben? – Veeram

+0

In den meisten Fällen müssen wir das letzte Produkt auswählen. Aber ich denke, ich habe ein ganz anderes Szenario, das Sie noch nie gehört haben. Egal was die Bestellung ist Ich möchte das Produkt auswählen, wenn es von einem Benutzer innerhalb einer Kategorie hinzugefügt wird. Da nicht nur die Produkte neu sortiert werden, sondern der Benutzer auch Produkte zu dieser Kategorie hinzufügen kann, besteht in diesem Fall die Möglichkeit, dass das Standardprodukt irgendwann vor oder unter demselben Produkt liegt, das vom Benutzer hinzugefügt wurde. Also, um dies zu machen, will ich, dass es nicht auf dem ersten oder letzten basiert, aber ich möchte dem Benutzer ein Produkt hinzufügen, entweder vor oder nach dem Standardprodukt. – Shravya

Verwandte Themen