Interrogation Mongodb sur le mois, le jour, l'année... d'une datetime [dupliquer]

cette question a déjà une réponse ici:

j'utilise mongodb et je stocke datetime dans ma base de données de cette façon""

pour une date "17-11-2011 18:00" je magasin:

date = datetime.datetime(2011, 11, 17, 18, 0)
db.mydatabase.mycollection.insert({"date" : date})

je voudrais faire une requête comme ça""

month = 11
db.mydatabase.mycollection.find({"date.month" : month})

ou

day = 17
db.mydatabase.mycollection.find({"date.day" : day})

quelqu'un sait comment faire cette requête?

38
demandé sur Neil Lunn 2011-11-15 16:55:52

7 réponses

Les Dates

sont stockées dans leur format timestamp. Si vous voulez tout ce qui appartient à un mois spécifique, interrogez pour le début et la fin du mois.

var start = new Date(2010, 11, 1);
var end = new Date(2010, 11, 30);

db.posts.find({created_on: {$gte: start, $lt: end}});
//taken from http://cookbook.mongodb.org/patterns/date_range/
45
répondu DrColossos 2011-11-15 13:09:24

vous ne pouvez pas interroger directement mongodb collections par date composants comme le jour ou le mois. Mais c'est possible en utilisant le spécial $où expression javascript

db.mydatabase.mycollection.find({$where : function() { return this.date.getMonth() == 11} })

ou simplement

db.mydatabase.mycollection.find({$where : 'return this.date.getMonth() == 11'})

(Mais je préfère le premier)

vérifiez les commandes shell ci-dessous pour obtenir les parties de date

>date = ISODate("2011-09-25T10:12:34Z")
> date.getYear()
111
> date.getMonth()
8
> date.getdate()
25

EDIT:

Utiliser $où seulement si vous n'avez pas d'autre choix. Ça vient avec les problèmes de performance. Veuillez consulter les commentaires de @kamaradclimber et @dcrosta ci-dessous. Je vais laisser ce post ouvert de sorte que les gens d'autres obtenez les faits à ce sujet.

et consultez le lien $where Clauses and Functions in Queries pour plus d'information

27
répondu RameshVel 2011-11-16 07:35:28

Que diriez-vous de stocker le mois dans sa propre propriété puisque vous avez besoin d'interroger pour elle? moins élégant que $where , mais susceptible de mieux fonctionner car il peut être indexé.

10
répondu RubyTuesdayDONO 2011-11-16 05:38:25

si vous souhaitez rechercher des documents qui appartiennent à un mois spécifique, assurez-vous de demander comme ceci:

// Anything greater than this month and less than the next month
db.posts.find({created_on: {$gte: new Date(2015, 6, 1), $lt: new Date(2015, 7, 1)}});

évitez les querelles comme ci-dessous autant que possible.

// This may not find document with date as the last date of the month
db.posts.find({created_on: {$gte: new Date(2015, 6, 1), $lt: new Date(2015, 6, 30)}});

// don't do this too
db.posts.find({created_on: {$gte: new Date(2015, 6, 1), $lte: new Date(2015, 6, 30)}});
8
répondu Ujjwal Ojha 2015-06-12 04:55:01

vous pourriez exécuter une opération d'agrégat avec le aggregate() fonction qui prend en $redact pipeline qui utilise le opérateurs D'agrégation de Date dans l'expression de condition:

var month = 11;
db.collection.aggregate([
    {
        "$redact": {
            "$cond": [
                { "$eq": [ { "$month": "$createdAt" }, month ] },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

pour l'autre requête

var day = 17;
db.collection.aggregate([
    {
        "$redact": {
            "$cond": [
                { "$eq": [ { "$dayOfMonth": "$createdAt" }, day ] },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

En utilisant ou

var month = 11,
    day = 17;
db.collection.aggregate([
    {
        "$redact": {
            "$cond": [
                { 
                    "$or": [ 
                        { "$eq": [ { "$month": "$createdAt" }, month ] },
                        { "$eq": [ { "$dayOfMonth": "$createdAt" }, day ] }
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

utilisant et

var month = 11,
    day = 17;
db.collection.aggregate([
    {
        "$redact": {
            "$cond": [
                { 
                    "$and": [ 
                        { "$eq": [ { "$month": "$createdAt" }, month ] },
                        { "$eq": [ { "$dayOfMonth": "$createdAt" }, day ] }
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    }
])

le $redact opérateur intègre la fonctionnalité de $project et $match pipeline and will return all documents match the condition using $$KEEP $$PRUNE variable.

3
répondu chridam 2017-02-20 12:06:41

, Vous pouvez rechercher des enregistrements par mois, jour, année, etc de dates par Date d'Opérateurs d'Agrégation , comme $dayOfYear, $dayOfWeek, $mois, $annee etc.

comme exemple si vous voulez toutes les commandes qui sont créées en avril 2016, vous pouvez utiliser la requête ci-dessous.

db.getCollection('orders').aggregate(
   [
     {
       $project:
         {
           doc: "$$ROOT",
           year: { $year: "$created" },
           month: { $month: "$created" },
           day: { $dayOfMonth: "$created" }
         }
     },
     { $match : { "month" : 4, "year": 2016 } }
   ]
)

ici créé est un champ de type date dans les documents, et $$ROOT nous avons utilisé pour passer tous les autres champs au projet dans la prochaine étape, et nous donner tous le détail des documents.

, Vous pouvez optimiser la requête ci-dessus selon votre besoin, c'est juste pour donner un exemple. Pour en savoir plus sur les opérateurs de date Aggregation, visitez le lien .

2
répondu Puneet Singh 2017-02-15 07:25:59

vous pouvez utiliser MongoDB_DataObject wrapper pour effectuer une telle requête comme ci-dessous:

$model = new MongoDB_DataObject('orders');

$model->whereAdd('MONTH(created) = 4 AND YEAR(created) = 2016');

$model->find();

while ($model->fetch()) {
    var_dump($model);
}

ou, de la même manière, en utilisant la chaîne de requête directe:

$model = new MongoDB_DataObject();

$model->query('SELECT * FROM orders WHERE MONTH(created) = 4 AND YEAR(created) = 2016');

while ($model->fetch()) {
    var_dump($model);
}
0
répondu CEDA 2017-02-16 04:49:00