2016-07-07 10 views
0

Ich brauche Hilfe/Ratschläge, wie man etwas SQL-Verhalten in MongoDB repliziert. Insbesondere diese Sammlung gegeben:MongoDb-Aggregation (SQL-UNION-Stil)

{ 
    "_id" : ObjectId("577ebc0660084921141a7857"), 
    "tournament" : "Wimbledon", 
    "player1" : "Agassi", 
    "player2" : "Lendl", 
    "sets" : [{ 
     "score1" : 6, 
     "score2" : 4, 
     "tiebreak" : false 
    }, { 
     "score1" : 7, 
     "score2" : 6, 
     "tiebreak" : true 
    }, { 
     "score1" : 7, 
     "score2" : 6, 
     "tiebreak" : true 
    }] 
} 
{ 
    "_id" : ObjectId("577ebc3560084921141a7858"), 
    "tournament" : "Wimbledon", 
    "player1" : "Ivanisevic", 
    "player2" : "McEnroe", 
    "sets" : [{ 
     "score1" : 4, 
     "score2" : 6, 
     "tiebreak" : false 
    }, { 
     "score1" : 3, 
     "score2" : 6, 
     "tiebreak" : false 
    }, { 
     "score1" : 6, 
     "score2" : 4, 
     "tiebreak" : false 
    }] 
} 
{ 
    "_id" : ObjectId("577ebc7560084921141a7859"), 
    "tournament" : "Roland Garros", 
    "player1" : "Navratilova", 
    "player2" : "Graf", 
    "sets" : [{ 
     "score1" : 5, 
     "score2" : 7, 
     "tiebreak" : false 
    }, { 
     "score1" : 6, 
     "score2" : 3, 
     "tiebreak" : false 
    }, { 
     "score1" : 7, 
     "score2" : 7, 
     "tiebreak" : true 
    }, { 
     "score1" : 7, 
     "score2" : 5, 
     "tiebreak" : false 
    }] 
} 

Und diese zwei unterschiedliche Aggregationen:

Aggregation ALFA): Diese Aggregation ist absichtlich seltsam, dass es in dem Sinne ist so konzipiert, alle Spiele zu finden, wo mindestens 1 Tiebreak ist wahr aber zeigen nur Sätze, wo Tiebreak falsch ist. Bitte beachten Sie nicht die Logik, es ist in Handarbeit gemacht, um die volle Freiheit für den Benutzer zu ermöglichen.

{ 
    $match: { 
     "tournament": "Wimbledon", 
     "sets.tiebreak": true 
    } 
}, 
{ 
    $project: { 
     "tournament": 1, 
     "player1": 1, 
     "sets": { 
      $filter: { 
       input: "$sets", 
       as: "set", 
       cond: { 
        $eq: ["$$set.tiebreak", false] 
       } 
      } 
     } 
    } 
} 

2) Aggregation BETA: diese Aggregation ist absichtlich seltsam, in dem Sinne, dass es alle Spiele finden entwickelt, in denen mindestens 1 Tiebreak falsch ist aber zeigen nur Sätze, wo Tiebreak wahr ist . Bitte beachten Sie nicht die Logik, es ist in Handarbeit gemacht, um die volle Freiheit für den Benutzer zu ermöglichen. Bitte beachten Sie, dass player1 vor den Ergebnissen verborgen ist.

{ 
    $match: { 
     "tournament": "Roland Garros", 
     "sets.tiebreak": false 
    } 
}, 
{ 
    $project: { 
     "tournament": 1, 
     "sets": { 
      $filter: { 
       input: "$sets", 
       as: "set", 
       cond: { 
        $eq: ["$$set.tiebreak", true] 
       } 
      } 
     } 
    } 
} 

Nehmen wir nun an, dass diese beiden Aggregationen Zweck zu begrenzen ist, welcher Teil der Datenbank ein Benutzer sehen kann, in dem Sinne, dass diese beiden Abfragen alle Dokumente begrenzen (und Einzelheiten), die für den Benutzer sichtbar sind. Dies entspricht 2 SQL-Ansichten, auf die der Benutzer Zugriffsrechte hat.

Ich möchte/wollte versuchen, die vorherigen eindeutigen Aggregationen in nur einer neu zu schreiben. Kann das erreicht werden?

Es ist zwingend, alle Beschränkung zu halten, die in Aggregation A gesetzt wurden & B, ohne jegliche Kontrolle über Daten zu verlieren und ohne Leckage und Daten, die nicht in Abfrage A oder B.

Insbesondere war, paßt in Wimbledon kann nur gesehen werden, wenn sie mindestens einen Satz hatten, der mit einem Tiebreak endete. Spieler1 Feld kann gesehen werden. Einzelne Sets müssen ausgeblendet werden, wenn sie nicht mit einem Tiebreak enden und sonst verborgen sind. Bei Bedarf ist es akzeptabel, aber nicht wünschenswert, Player1 überhaupt nicht zu sehen.

Umgekehrt können Spiele in Roland Garros nur gesehen werden, wenn sie mindestens einen Satz hatten, der ohne einen Tie-Break endete. Das Feld Player1 MUSS versteckt sein. Einzelne Sätze müssen gesehen werden, wenn sie mit einem Tiebreak geendet haben und sonst verborgen sind.

Wiederum besteht der Zweck darin, die beiden Aggregationen zu verbinden, während die durch die beiden Aggregationen vorgegebenen Grenzen eingehalten werden.

MongoDB ist Version 3.5, kann bei Bedarf auf instabile Versionen aktualisiert werden.

+0

wäre es ein Extra, Reguläre Ausdrücke in Textfiltern zu verwenden. Leistungsorientierte Strategien sind ein Plus, aber nicht zwingend erforderlich. – Manuele

+0

Es scheint mir, dass Sie Daten aus einer einzigen Sammlung ziehen, um beide Arten von Daten versuchen $ oder. UNION zieht normalerweise aus verschiedenen Tabellen mit ähnlichen Spalten. – Tiramisu

+0

Ja, ich ziehe aus der gleichen Sammlung ... aber leider ist der Punkt nicht in der $ match-Phase (mit $ oder ...), sondern die $ Projektstufe, die mir unmöglich/zu schwierig scheint ... Danke Sowieso! – Manuele

Antwort

0

hier ist meine zwei Cent für die Ausgabe:
, wenn Sie leere Sätze vermeiden wollen, wenn

  • ein "Wimbledon" doc hat alletrue tibreaks,
  • oder "Roland Garros "hat allefalse Tiebreaks

können Sie die Abfrage neu zu gestalten:

... 
{ 
    $and: [{ 
    "sets.tiebreak": true, 
    }, { 
    "sets.tiebreak": false 
    }], 
    $or: [{ 
    "tournament": "Wimbledon" 
    }, { 
    "tournament": "Roland Garros" 
    }] 
} 
... 

und es in Verwendung: Aggregat

+0

Schwer zu sagen, welches das richtige Verhalten ist, da dies nur ein Test war. Der Sinn davon war, eine SQL UNION nachzuahmen. Da "Aggregation ALFA/BETA" leere Mengen zurückgeben würde, denke ich, dass meine Abfrage immer noch am korrektesten ist, aber Ihre Notiz weist auf eine mehr als korrekte Anmerkung hin. Es wäre schön, die zwei verschiedenen Ansätze zu benchmarken. Ich denke mehr Bühnen = mehr Zeit, aber es könnte auch sein, dass eine * harte * Projektion vielleicht mehr Zeit in Anspruch nimmt als eine Liste von Matches/Abwicklungen/Matches ... Wird untersuchen ... – Manuele

+0

Ich werde deine Antwort nicht als die markieren korrigieren Sie einen für die Gründe im vorherigen Kommentar, aber es ist sicherlich ein gültiger Ansatz. – Manuele