2017-10-12 3 views
0

Vous essayez de générer une requête agrégée qui me permettrait de classer les codes zip et de renvoyer le nombre de chaque groupe.Regrouper les codes postaux dans de nouvelles catégories s'il contient une valeur dans le tableau

Le docuement regarde en partie comme

{ 
"_id" : ObjectId("value"), 
"updatedAt" : ISODate("value"), 
"zip" : "11209", 
"state" : "NY", 
"city" : "New York", 
} 

Je voudrais groupe en comparant le champ « zip » à un tableau avec un nombre n de valeurs mutuellement exclusives

east_ny_zipcodes = [11209, 11210, 11211, ...] 
lower_ny_zipcodes = [11212, 11213, 11214, ...] 

idéalement retour quelque chose comme

{ 
lower_ny: 1200, 
upper_ny: 1500, 
east_ny: 2000 
} 
+1

Vous pouvez utiliser '$ group' avec' $ cond' et comparer des tableaux pour chaque catégorie dans son propre cond. Quelque chose comme 'db.collection_name.aggregate ({ "groupe $": { "_id": null, "east_ny": { "somme $": { "$ cond": [{ « $ en « : [ "zip $", " east_ny_zipcodes" ] }, 1, ] }} }} )'. Vous pouvez ajouter l'étape '$ match' avec' $ or' pour limiter les codes postaux à traiter dans le pipeline. – Veeram

Répondre

1

Avec MongoDB depuis 3.4, vous pouvez utiliser $in pour obtenir une comparaison à un tableau:

db.zips.aggregate([ 
    { "$group": { 
    "_id": null, 
    "lower_ny": { 
     "$sum": { 
     "$cond": [{ "$in": [ "$zip", lower_ny_zipcodes ] },1,0] 
     } 
    }, 
    "east_ny": { 
     "$sum": { 
     "$cond": [{ "$in": [ "$zip", east_ny_zipcodes ] },1,0] 
     } 
    }, 
    "upper_ny": { 
     "$sum": { 
     "$cond": [{ "$in": [ "$zip", upper_ny_zipcodes ] },1,0] 
     } 
    } 
    }} 
]) 

Si vous ne l'avez pas alors il est $setIsSubset depuis MongoDB 2.6. Un peu différent dans la syntaxe et l'intention. Mais vos listes sont « uniques » il est donc pas un problème:

db.zips.aggregate([ 
    { "$group": { 
    "_id": null, 
    "lower_ny": { 
     "$sum": { 
     "$cond": [{ "$setIsSubset": [ ["$zip"], lower_ny_zipcodes ] },1,0] 
     } 
    }, 
    "east_ny": { 
     "$sum": { 
     "$cond": [{ "$setIsSubset": [ ["$zip"], east_ny_zipcodes ] },1,0] 
     } 
    }, 
    "upper_ny": { 
     "$sum": { 
     "$cond": [{ "$setIsSubset": [ ["$zip"], upper_ny_zipcodes ] },1,0] 
     } 
    } 
    }} 
]) 

En substance, il est juste une comparaison logique à votre contenu du tableau externe défini, qui obtient étendu dans le contenu BSON envoyé comme l'opération.

Bien sûr, vos valeurs dans le tableau doivent également être "chaînes" afin de correspondre. Mais cela est facile si vous ne l'avez pas déjà fait:

east_ny_zipcodes = [11209, 11210, 11211, ...].map(n => n.toString()); 
+0

Est-il possible de lui faire retourner à la fois le compte pour chaque catégorie, mais aussi la liste des éléments groupés comme le ferait une requête $ eq normale. Vous voulez faire une vérification sur place pour vous assurer que c'est juste. Merci! J'utilisais l'opérateur $ in mais je n'utilisais pas le $ cond en premier. Merci pour la clarification. –

+0

@MeirSnyder Vous semblez demander ['$ push'] (https://docs.mongodb.com/manual/reference/operator/aggregation/push/) qui est un autre accumulateur qui construit un tableau à partir du contenu trouvé dans le éléments correspondant aux limites de regroupement. Notez que la limite de 16 Mo s'applique toujours, donc si vous construisez des documents groupés avec un contenu de tableau qui enfreint ce que vous allez erreur. Alternativement, '$ in' renvoie juste un booléen, donc vous pouvez toujours' $ project' ou '$ addFields' avec l'évaluation booléenne à côté des données existantes sans aucun regroupement. –