DIY-Stories

Mongodb: Wie vergleiche ich zwei Felder aus einer Projektion?

Mongodb: Wie vergleiche ich zwei Felder aus einer Projektion?

Unter MongoDB ist es möglich, Informationen in Form von mehr oder weniger komplexen Objekten zu speichern. Es kann vorkommen, dass man mehrere Felder aus einem Teilobjekt einer Sammlung vergleichen will.

In unserem Beispiel werden wir eine Produktkollektion verwenden, in der das Preisfeld verschiedene Preise (Kauf, HT, TTC-Verkauf, …) definieren wird. 

Struktur der Sammlung

Produktkollektion

Das Preisfeld enthält hier 2 Werte, die wir vergleichen werden:

  • Verkaufspreis ohne MwSt.,
  • der Verkaufspreis inkl.

=> Daten im Originalformat

Wie kann man eine Projektion mit Filter durchführen?

Da diese Daten komplex sind, ist es nicht möglich, die Werte direkt miteinander zu vergleichen. Dazu ist es notwendig, eine Projektion zu durchlaufen.

Abfrage

[
    {
        '$project': {
            'prix_vte': {
                '$filter': {
                    'input': '$prix', 
                    'as': 'list', 
                    'cond': {
                        '$eq": [
                            $list.id, prix_vente_ht_eur.
                        ]
                    }
                }
            }, 
            'prix_vte_ttc': {
                '$filter': {
                    'input': '$prix', 
                    'as': 'list', 
                    'cond': {
                        '$eq": [
                            $list.id, prix_vente_ttc_eur.
                        ]
                    }
                }
            }
        }
    }, {
        '$match": {
            '$expr': {
                '$gte": [
                    '$prix_vte.wert', '$prix_vte_ttc.wert'
                ]
            }
        }
    }
]

1 Datenprojektion

Zuerst führen wir eine Projektion "$project" durch, um informationen Namen zu filtern und zu nennen, um sie in unserem Filter "$match" zu verwenden.

In'prix_vte'beziehen wir das Filterergebnis '$filter' auf das Preisfeld mit dem Wert 'id' = 'prix_vente_ht_eur'

Dasselbe gilt für'prix_vte_ttc'das Ergebnis des Filters '$filter' auf das Preisfeld mit dem Wert 'id' = 'prix_vente_ttc_eur'.

=> Daten im projektierten Format

project produkt

2 Vergleich der Werte

Dann bleibt der letzte Schritt, unsere 2 Werte mit einem '$match' als Ausdruck zu vergleichen oder zu testen, ob '$prix_vte' >= '$prix_vte_ttc'

'$match": {
            '$expr': {
                '$gte": [
                    '$prix_vte.wert', '$prix_vte_ttc.wert'
                ]
            }
        }

3 Wiederherstellung der Ergebnisse

project produkt

Am Ende bleiben nur noch die Aufnahmen, die den Test bestehen.Diese Aufzeichnungen sind in dem format, das zuvor bei der Projektion festgelegt wurde.

Wie kann ich die Anfrage ausführen?

Es genügt, die Abfrage mit Hilfe der Funktion 'Aggregate' auszuführen, indem Sie folgendermaßen vorgehen:

db.Erzeugnis.Aggregate [{ ‘$project’: { ‘prix_vte’: { …… }] ()

Andere Fälle

In einfacheren Fällen, wenn unsere 2 Felder verglichen sind nur Felder, gibt es mehrere Möglichkeiten, um 2 Felder zu vergleichen.

Hier keine komplexen Daten, nur 2 Felder vom Typ 'doppel'

Das Äquivalent der MySQL-Abfrage würde folgendes geben:

SELECT * FROM MaCollection
Feld1 > Feld2

Verwenden Sie $where

Sie können ein '$where' verwenden. Bitte beachten Sie einfach, dass dies langsam sein wird (denn Javascript-Code muss auf jeder Registrierung ausgeführt werden), also denken Sie daran, indexe richtig zu erstellen.


db.MaCollection.find { $where: function () {return this.champ1 > this.champ2 } } }

Oder einfach:

db.MaCollection.find ( $where: "this.champ1 > this.champ2"});

Wenn Ihre Anfrage nur aus einem $where können Sie sogar nur den Javascript-Code übermitteln.


db.MaCollection.find ( "this.champ1 > this.champ2");

Der Ausdruck $expr

Seit MongoDB 3.6 ist es möglich, die Ggregationsfunktionen in einer normalen 'find' Abfrage zu verwenden.


db.MaCollection.find{ $expr:{$gt}} ["$champ1", "$champ2"]

Oder im Antrag auf Verdauung


db.MaCollection.Aggregate$match:{$expr:$gt} ["$champ1", "$champ2"]

Die Projektionen bis

Es kommt manchmal vor, dass viele Aufnahmen bei einer Suche verarbeitet werden müssen. Um die Bearbeitungsgeschwindigkeit erheblich zu beschleunigen, ist es manchmal notwendig, Projektionen zu heranziehen.

Wir sind hier für den Fall, dass unsere Sammlung mehrere Tausend Aufnahmen mit etwa 30 Feldern enthält

Test mit einem klassischen 'find'

Ansprechzeit von 4.41s

db.MaCollection.find ( $where: "this.champ1 > this.champ2"});
Test mit einem '$project'

Ansprechzeit von 185ms

db.MaCollection.aggregate ([
    {
        '$project': {
            "isGreater": [ "$champ1", "$champ2" ] {$cmp},
            Feld 1,
            'Feld2': 1
        }
    },
    {
        '$match': {'isGreater': 1 }
    }
]))

Durch die Projektion holen wir nur unsere Felder 1 und 2 zurück, sowie das Ergebnis des Vergleichs von Champ1 und Champ2, den wir in das Feld'isGreater' setzen, das wir testen. 

Laisser un commentaire