2017-10-20 23 views
2

Je dois obtenir la première occurrence dans la dernière séquence de données insérée dans la base de données. Ce serait génial si cela pouvait être fait en une seule requête.Obtenir la première occurrence dans la dernière séquence avec des données

Disons que j'ai données comme ceci:

{_id:......,ts:Date("2017-10-24T00:00:00.000Z"), id: 1, ok: false} 
{_id:......,ts:Date("2017-10-23T00:00:00.000Z"), id: 1, ok: false} 
{_id:......,ts:Date("2017-10-22T00:00:00.000Z"), id: 1, ok: true} 
{_id:......,ts:Date("2017-10-21T00:00:00.000Z"), id: 1, ok: true} 
{_id:......,ts:Date("2017-10-20T00:00:00.000Z"), id: 1, ok: false} 
{_id:......,ts:Date("2017-10-21T00:00:00.000Z"), id: 2, ok: false} 
{_id:......,ts:Date("2017-10-20T00:00:00.000Z"), id: 2, ok: true} 

et je dois obtenir pour chaque ID de la première occurrence lorsque le ok de terrain était faux dans la dernière séquence lorsque le ok est faux.

{_id:......,ts:Date("2017-10-23T00:00:00.000Z"), id: 1, ok: false} 

mais j'en ai besoin pour chaque identifiant. Il me semble impossible de le faire évolutif, donc je n'aurai pas besoin de x milliers de requêtes à la base de données. Je sais comment faire pour un ID mais si j'avais besoin d'envoyer une requête pour chaque ID, la base de données serait dépassée.

Voici ma requête en cours:

{ 
    $sort : {ts : -1} 
}, 
{ 
    $match : {"ok" : true } 
}, 
{ 
    $group : { 
     _id : {id : "$id"}, 
     last : {$last : "$$CURRENT"} 
    } 
} 

Cela me donne pour chaque identifiant les dernières données avec ok vrai.

Mais j'ai besoin des données après. Y at-il une manière simple et modulable de le faire pour le faux ok?

J'ai essayé d'utiliser la fonction foreach sur l'ensemble, mais si je fais ce que j'obtiens l'erreur

TypeError: db.getCollection(...).aggregate(...).foreach is not a function

donc je ne sais pas, alors ... est-il possible de le faire?

Répondre

1

Je pense que vous n'avez pas passé une fonction en tant que paramètre de ForEach:

db.getCollection(...).aggregate(...).ForEach(function(myDoc) { 
         print(myDoc.ts); 
         }); 

Ensuite, en ce qui concerne l'agrégation, je ne suis pas sûr que ce soit possible. Comme le document est quelque peu lié par une séquence virtuelle. Je le ferais comme suit:

  • créer un curseur avec une requête triée par date et ID.
  • itérer avec foreach (cela extraire les données par des séquences de 20 docs, vous ne serez pas se retrouver avec toute la collection en mémoire (soit sur le client ou DB))
  • ont quelques déclarations qui, si les chèques si la séquence est vraie/fausse et imprime la première occurrence de la dernière fausse séquence.