2017-06-27 1 views
1

Meine grundlegende Struktur ist Ich habe Benutzerobjekt mit einem Session-Objekt, das eine subjectId und einen Stundenpreis enthält.

User{ 
    defaultHourly: Number, 
    subjects{ 
     [ 
      id: String, 
      hourly: Number 
     ] 
    } 
}  

Ich benutze elemMatch wie folgt aus:

query.elemMatch("subjects", { 
       "id": { $in: subjects }, 
       "$or": [ 
        { "hourly": { $eq: null } }, // this is my issue 
        { 
         "$and": [ 
          { "hourly": { $ne: null } }, 
          { "hourly": { $gte: price.low, $lte: price.high } } 
         ] 
        } 
       ] 
      }); 

der erste Teil des elemMatch stellt sicher, dass die subjectId Ich möchte in der Reihe von Themen ist. Dann möchte ich nach Preis filtern. Wenn ein Benutzer im stündlichen Feld null hat, möchte ich den defaultHourly mit price.low und price.high vergleichen.

Das Problem ist, dass defaultHourly ist kein Feld in den Fächern, aber ist ein Feld in den Eltern der Themen, so dass ich nicht sicher bin, wie Sie darauf zugreifen.

Ich möchte schreiben:

"$or": [ 
      { 
       "$and": [ 
        { "hourly": { $eq: null } }, 
        { "defaultHourly": { $gte: price.low, $lte: price.high } } //this doesnt work because default hourly is not a field. 
       ] 
      }, 
      { 
       "$and": [ 
        { "hourly": { $ne: null } }, 
        { "hourly": { $gte: price.low, $lte: price.high } } 
       ] 
      } 
     ] 
}); 

Wie kann ich diese Multi-Level-Vergleich tun?

Antwort

1

Sie schreiben die Bedingung außerhalb der $elemMatch, und legen Sie die $or auf der obersten Ebene des Dokuments. Dies ermöglicht jedem „Satz“ von Bedingungen gelten:

User.find({ 
    "$or": [ 
    { 
     "defaultHourly": { "$gte": price.low, "$lte": price.high }, 
     "subjects": { 
     "$elemMatch": { 
      "id": { "$in": subjects }, 
      "hourly": { "$eq": null } 
     } 
     } 
    }, 
    { 
     "subjects": { 
     "$elemMatch": { 
      "id": { "$in": subjects }, 
      "hourly": { "$gte": price.low, "$lte": price.high } 
     } 
     } 
    } 
    ] 
}) 

Beachten Sie auch die $ne nicht benötigt wird, da die „Reichweite“ Vergleich tatsächlich null negieren würde, da es einfach nicht sein „größer als“ einen tatsächlichen numerischen Wert .

Beachten Sie außerdem, dass ALLE MongoDB-Abfrageausdrücke bereits UND-Bedingungen sind, z. B. $gte und $lte für dieselbe Eigenschaft. Also auch wenn es nicht erforderlich ist, kann die $ne auch geschrieben werden als:

"hourly": { "$gte": price.low, "$lte": price.high, "$ne": null } 

Welche keine Notwendigkeit für eine explizites $and entfernt.

Verwandte Themen