Comment faire en sorte que Perl Mongo find() renvoie les enregistrements dont ts a moins de 5 jours ?

StackOverflow https://stackoverflow.com//questions/22084245

  •  24-12-2019
  •  | 
  •  

Question

J'ai une collection MongoDB appelée Clickstream et je souhaite trouver tous les documents correspondant à un pubCode spécifique avec un horodatage au cours des 5 derniers jours.L'horodatage se trouve dans un champ appelé ts, avec un type de données Mongo Date.

À partir du shell Mongo, je peux exécuter ce qui suit : -

    db.Clickstream.find({
        pubCode : "w_abc123",
        ts: {$gte: ISODate("2014-02-28T00:00:00Z")}
    })

Cependant, je n'arrive pas à faire la même chose en Perl (en utilisant la date du jour plutôt qu'une date et une heure codées en dur).Si je fais ça :-

    my $now = DateTime->now;
    my $n_days_ago = $now->add( days => -5 );
    ... etc ...
    my $ptr = $ptrClickstream->find(
        {
            pubCode => "$pubCode",
            ts => { "\$gte" => ISODate("$n_days_ago") }
        }, 
        { hitType => 1 }
    );

Je reçois le message d'erreur suivant:-

Sous-programme non défini &main::ISODate appelé à la ligne 25 de recalcPubPop.pm.

Et si je supprime la référence à ISOData() comme ça

    my $ptr = $ptrClickstream->find({
        pubCode => "$pubCode", ts => { "\$gte" => "$n_days_ago" }
    });

Je ne reçois aucun document retourné.

Des suggestions sur la façon de faire en sorte que ce find() renvoie les enregistrements où ts a moins de 5 jours ?Merci!

Était-ce utile?

La solution

Utiliser DateHeure naturellement.Je viens d'expliquer dans son intégralité.

Alors où tu vois ça ISODate se forme à partir de la coquille du mongo, c'est-à-dire en fait juste une représentation native pour l'environnement JavaScript du shell de la date BSON sous-jacente qui est réellement stockée.

Ainsi, le pilote Perl "gonfle" ces valeurs comme DateHeure objets lorsque vous les récupérez, et gère de la même manière la conversion en date BSON lorsque vous transmettez les valeurs.

Donc tu as déjà fait le DateHeure partie mathématique dans votre code :

my $now = DateTime->now;
my $n_days_ago = $now->add( days => -5 );

Pour référence ->add fonctionne "sur place" et vous semblez vouloir le "début" de la journée pour que nous puissions tronquer.

Essayez de forcer les dates "UTC", ce qu'elles seront dans la collection. C'est juste pour être complet, car elles devraient généralement être ainsi.Vous trouverez peut-être cette forme de codage de votre date un peu plus propre :

my $then = DateTime->now( time_zone => 'UTC' )
             ->truncate( to => 'day' )->add( days => -5 );

Et votre deuxième formulaire de requête était généralement correct, mais votre vrai problème c'était toi, nous sommes contraints de chaîner en interpolant comme dans "$n_days_ago", donc vous n'aviez pas l'objet mais la chaîne.Consultez le formulaire tel que je l'ai modifié et n'essayez pas d'interpoler à moins que vous n'ayez vraiment l'intention de :

my $ptr = $ptrClickstream->find({
    pubCode => $pubCode, ts => { '$gte' => $then } 
});

Donc tout cela fonctionne pour moi.Si cela ne renvoie pas de résultat, vérifiez votre vars que leurs valeurs correspondent définitivement à vos attentes.

Toutes les implémentations de pilotes gèrent de cette manière les « objets date » natifs pour leur langage.

Pour plus d'informations, consultez la section pilote sur Rendez-vous.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top