#python-3.x #datetime #nested #pymongo
#python-3.x #datetime #вложенный #pymongo
Вопрос:
Как вы можете запросить db.collection по датам, когда даты хранятся в виде строк?Поскольку эта база данных большая и постоянно растущая, цикл for для преобразования каждого datetime не имеет смысла для долгосрочного решения.
Я создаю конвейер для запроса коллекции по любым заданным датам, но каждый запрос, который я пытаюсь выполнить, приводит к пустому списку [].
формат даты: «ts»: «2018-09-26T21:02:19 00:00»
Я ищу решение, которое позволяет избежать преобразования ключа datetime в цикле for, потому что база данных растет, и это заняло бы больше времени, чем выполнение запроса, отличного от 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"}
Я что-то здесь упускаю? Это проблема форматирования?
Ответ №1:
вы можете преобразовать строку в datetime и сравнить их следующим образом:
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» в вашем документе, но для преобразования и сравнения даты вы можете сделать это.
вы можете преобразовать datetime в строку и выполнить поиск по своему усмотрению. Сделайте это:
a = datetime.now()
now = a.strftime("%Y-%m-%dT%X 00:00")
И теперь вы можете использовать метод find.
для запроса в массиве:
db.collection.find( { "d": { $elemMatch: {"ts" : {'$lt':end, '$gt':start } } } )
Комментарии:
1. Привет, Али, спасибо за ответ. Таким образом, преобразование всего в коллекции в цикле for заняло бы гораздо больше времени, чем просто подстановка данных другим ключом -> затем форматирование в pandas dataframe -> преобразование в datetime с последующей подстановкой таким образом. Я делаю это сейчас, и это не является долгосрочным решением, поскольку база данных растет. Возможно ли подмножество коллекции по датам в текущем формате ts? Я отредактирую OP, чтобы предоставить больше контекста. Спасибо.
2. я отредактировал OP в разделе о решениях, которые не включают преобразование всего в datetime. Этот метод работает, но слишком медленный для того, что я ищу.
3. вы можете преобразовать datetime в строку, как указано выше. Я думаю, это будет работать быстрее.
4. Выдает «KeyError: ‘ts’ «. Можете ли вы подробнее рассказать о цикле в «d» в документе?
5. Привет — теперь получаю «KeyError: ‘d'» — есть идеи, почему?