【问题标题】:(Python) Query by dates that are stored as strings in mongoDB collection(Python) 按日期查询,在 mongoDB 集合中存储为字符串
【发布时间】:2019-08-17 08:17:20
【问题描述】:

当日期存储为字符串时,如何按日期查询 db.collection? 由于该数据库很大且不断增长,因此用于转换每个日期时间的 for 循环在很长一段时间内没有意义长期解决方案。

我正在创建一个管道来查询任何给定日期的集合,但我尝试的每个查询都会导致一个空列表 []。

日期格式: "ts": "2018-09-26T21:02:19+00:00"

我正在寻找一种避免在 for 循环中重新格式化 datetime 键的解决方案,因为数据库正在增长,并且它比运行非 datetime 查询需要更长的时间,然后在脚本下游转换为 pandas 然后转换为 datetime。

我已经尝试了各种 SO 帖子的几次尝试,但它们产生了空结果: 1.

n = db.collection.find({'ts':{'$lt':datetime.now(), '$gt':datetime.now() - timedelta(hours=10000)}})

print(n)
[]

2.:

start = datetime(2019, 2, 2, 6, 35, 6, 764)
end = datetime(2019, 2, 20, 6, 55, 3, 381)

doc = db.collection.find({'ts': {'$gte': start, '$lt': end}})
print(doc)
[]

但是我开始认为这是我的日期在 ts 键中的格式。下面是一个文档示例:

{
"_id": {
    "$oid": "5babf3dab512dd0165efd36c"
},
"d": [
    {
        "d": [
            17317,
            16556,
            9680,
            55982,
            45948
        ],
        "h": 74.65,
        "ts": "2018-09-26T21:02:19+00:00",
        "p": [
            61,
            76,
            137,
            152,
            122
        ],
        "si": "9829563c95d0155f",
        "t": 24.82,
        "ti": "0000000000000000"
    },
    {
        "d": [
            17821,
            17488,
            9199,
            56447,
            44089
        ],
        "h": 80.09,
        "ts": "2018-09-26T21:02:19+00:00",
        "p": [
            61,
            76,
            137,
            152,
            122
        ],
        "si": "a42fbc88a44a316f",
        "t": 25.1,
        "ti": "0000000000000000"
    }
],
"gi": "GW-P1007"}

我在这里错过了什么吗?这是格式问题吗?

【问题讨论】:

    标签: python-3.x datetime nested pymongo


    【解决方案1】:

    您可以将字符串转换为日期时间并像这样比较它们:

    from datetime import datetime
    from datetime import timedelta
    q = list(db.collection.find())
    result = []
    for i in q:
        for j in i["d"]:
            time = datetime.strptime(j["ts"], "%Y-%m-%dT%X+00:00")
            end = datetime.now()
            start = end - timedelta(hours=10000)
            if time >= start and time <= end:
                result.append(i) #or append all document
    

    正如我在您的数据中看到的,我认为您应该在文档中的“d”中创建一个循环,但是对于转换和比较日期,您可以这样做。

    您可以将日期时间转换为字符串并按照您的意愿进行查找。这样做:

    a = datetime.now()
    now = a.strftime("%Y-%m-%dT%X+00:00")
    

    现在你可以使用 find 方法了。 在数组中查询:

     db.collection.find( { "d": { $elemMatch: {"ts" : {'$lt':end, '$gt':start } } } )
    

    【讨论】:

    • 嗨,阿里感谢您的回复。因此,在 for 循环中转换集合中的所有内容比仅通过另一个键对数据进行子集化需要更长的时间 -> 然后格式化为 pandas 数据框 -> 转换为 datetime 然后以这种方式进行子集化。我现在正在这样做,并且不是一个长期的解决方案,因为数据库正在增长。是否可以按当前 ts 格式的日期对集合进行子集化?我将编辑 OP 以提供更多上下文。谢谢。
    • 我将 OP 编辑​​为关于不涉及将所有内容转换为日期时间的解决方案。这种方法有效,但对于我正在寻找的东西来说太慢了。
    • 你可以像上面那样将日期时间转换为字符串。我认为它会更快。
    • 它给出了一个“KeyError: 'ts'”。您能详细说明文档中“d”中的一个循环吗?
    • 嘿 - 现在收到“KeyError: 'd'” - 知道为什么吗?
    猜你喜欢
    • 1970-01-01
    • 2021-02-26
    • 1970-01-01
    • 2021-06-12
    • 2023-04-08
    • 2016-04-09
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多