3

Я использую Джанго с Монго и у меня есть этот тип модели:Сортировка по дате в поле Datetime в Монго

class ProductDate(EmbeddedDocument): 
    created = DateTimeField() 
    updated = DateTimeField(null=True) 

class Product(Document): 
    product_id = IntField() 
    saves = IntField(default=0) 

    title = StringField(max_length=1000) 
    gender = StringField(choices=settings.GENDER_CHOICES, default=settings.UNISEX, max_length=50) 
    date = EmbeddedDocumentField(ProductDate) 

Теперь с этим, когда я делаю запрос так:

queryset = queryset.filter(title=search) 

Я хочу заказать сначала по дате в созданном поле DateTime, а затем упорядочить с помощью сохранения. Таким образом, продукты с одинаковой датой, а не временем, упорядочиваются по числу сохранений. Тем не менее, я не могу найти способ превратить диатомит на сегодняшний день, так что он сравнивает только дату.

Я не могу сделать:

.order_by("-date__created","-saves") 

потому что заказы в зависимости от времени.

Я попытался использовать агрегат в Монго, с этим руководством:

http://www.codewrecks.com/blog/index.php/2014/10/13/aggregate-in-mongo-using-only-date-part-of-a-datetime-property/

но did't помочь мне.

Может ли кто-нибудь, пожалуйста, направить меня к тому, как я могу это сделать? Спасибо!

ответ

3

Вы должны использовать _get_collection() accesssor, чтобы получить на подстилающий .aggregate() метод из коллекции PyMongo, а затем использовать $project для создания информации усеченной дат.

Вы можете использовать date aggregation operators:

Product._get_collection.aggregate([ 
    { "$project": { 
     "product_id": 1, 
     "saves": 1, 
     "title": 1, 
     "gender": 1, 
     "date": 1, 
     "partDate": { 
      "year": { "$year": "$date.created" }, 
      "dayOfYear": { "$dayOfYear": "$date.created" } 
     } 
    }}, 
    { "$sort": { 
     "partDate.year": -1, 
     "partDate.dayOfYear": -1, 
     "saves": -1 
    }} 
]) 

Или с датой математике вместо:

Product._get_collection.aggregate([ 
    { "$project": { 
     "product_id": 1, 
     "saves": 1, 
     "title": 1, 
     "gender": 1, 
     "date": 1, 
     "truncDate": { 
      "$subtract": [ 
       { "$subtract": [ 
        "$date.created", 
        datetime.datetime.utcfromtimestamp(0) 
       ] }, 
       { "$mod": [ 
        { "$subtract": [ 
         "$date.created", 
         datetime.datetime.utcfromtimestamp(0) 
        ] }, 
        1000 * 60 * 60 * 24 
       ]} 
      ] 
     } 
    }}, 
    { "$sort": { "truncDate": -1, "saves": -1 }} 
]) 

Последние работы по когда вы делаете математические операции на Date BSON объекта результат является метка времени Unix значение от секунд до эпохи. Таким образом, вычитание даты эпохи дает значение временной метки, которое затем округляется до одного дня.

- EDIT -

еще лучше, немного больше математики и вы возвращаете BSON Date, который транслирует назад для API. Просто нанесите $add превратить числовое значение обратно в BSON Дату:

Product._get_collection.aggregate([ 
    { "$project": { 
     "product_id": 1, 
     "saves": 1, 
     "title": 1, 
     "gender": 1, 
     "date": 1, 
     "truncDate": { 
      "$add": [ 
       { "$subtract": [ 
        { "$subtract": [ 
         "$date.created", 
         datetime.datetime.utcfromtimestamp(0) 
        ]}, 
        { "$mod": [ 
         { "$subtract": [ 
          "$date.created", 
          datetime.datetime.utcfromtimestamp(0) 
         ]}, 
         1000 * 60 * 60 * 24 
        ]} 
       ]}, 
       datetime.datetime.utcfromtimestamp(0) 
      ] 
     } 
    }}, 
    { "$sort": { "truncDate": -1, "saves": -1 }} 
]) 

что то же самое основное применение даты эпохи, используемая в остальной части преобразования.

- END -

Тогда вы можете $sort на соответствующем поле.

Конечно, это «сырые» объекты и больше не документы mongoengine, но тогда результат агрегации редко бывает точно таким же, как и ввод коллекции. Разумеется, в этом случае вы можете выбрать соответствующие поля и повторить в свой тип документа, если это необходимо. Или иначе просто работайте с результатами как есть.

+0

Wow! Спасибо! Считаете ли вы, что было бы лучше добавить другое поле в ProductDate, чтобы хранить только дату, а не время? Будет ли это эффективно? Благодаря! – Nazariy1995

+1

@ Brenden1995 Да, конечно, если вы можете перейти непосредственно к сортировке без вычисления чего-либо, тогда запрос будет быстрее. Кроме того, «нет ничего свободного», поэтому очевидной стоимости становится больше места. Но это ваше решение относительно того, стоит ли увеличение скорости в пространстве в зависимости от ваших собственных ограничений. –

 Смежные вопросы

  • Нет связанных вопросов^_^