【问题标题】:Sort by date in Datetime field in mongo在 mongo 的 Datetime 字段中按日期排序
【发布时间】:2015-07-09 02:39:52
【问题描述】:

我正在使用 django 和 mongo,我有这种类型的模型:

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")

因为按时间排序。

我在本教程中尝试在 mongo 中使用聚合:

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

但这对我没有帮助。

有人可以指导我如何做到这一点吗? 谢谢!

【问题讨论】:

    标签: django mongodb datetime django-rest-framework mongoengine


    【解决方案1】:

    您需要使用_get_collection() 访问器从pymongo 集合中获取底层.aggregate() 方法,然后使用$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 时间戳值。因此减去纪元日期会产生一个时间戳值,然后将其四舍五入为一天。

    -- 编辑--

    更好的是,多做一点数学运算,然后您返回一个 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 }}
    ])
    

    与其余转换中使用的基本纪元日期应用程序相同。

    -- 结束--

    然后您可以在相应的字段上$sort

    当然,这些是“原始”对象,不再是 mongoengine 文档,但是聚合输出很少与集合输入完全相同。当然,在这种情况下,您可以选择相关字段并在需要时重新转换为您的文档类型。或者按原样处理结果。

    【讨论】:

    • 哇!谢谢你!您认为向 ProductDate 添加另一个字段是否会更好,以便仅存储日期而不存储时间?那会有效吗?谢谢!
    • @Brenden1995 是的,当然,如果您可以直接进行排序而不计算任何内容,那么查询会更快。此外,“没有什么是免费的”,因此明显的成本有更多的空间。但这取决于您自己的限制,决定速度增益是否值得空间。
    猜你喜欢
    • 2014-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    相关资源
    最近更新 更多