АКТУАЛИЗАЦИЯ:
Фундаментално погрешно разбрах проблема. Феликс правеше запитване към mongoDB, за да разбере колко елемента попадат във всеки диапазон; следователно подходът ми не проработи, защото се опитвах да попитам mongoDB за елементите. Феликс разполага с много данни, така че това е напълно неразумно.
Феликс, ето актуализирана функция, която трябва да прави това, което искаш:
def getDataFromLast(num, quantum):
m = my_mongodb()
all = []
not_deleted = []
today = datetime.combine(date.today(), time())
for i in range(num+1)[-1]: # start from oldest
day = today - i*quantum
time_query = {"$gte":day, "$lt": day+quantum}
all.extend(m.data.find({"time":time_query}).count())
not_deleted.extend(m.data.find({"deleted":0, "time":time_query}).count())
return all, not_deleted
Quantum е „стъпката“, с която да погледнем назад. Например, ако искаме да разгледаме последните 12 часа, бих задал quantum = timedelta(hours=1)
и num = 12
.Актуализирано примерно използване, при което получаваме последните 30 дни, би било:
from datetime import datetime, date, time, timedelta
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from my_conn import my_mongodb
#def getDataFromLast(num, quantum) as defined above
def format_date(x, N, pos=None):
""" This is your format_date function. It now takes N
(I still don't really understand what it is, though)
as an argument instead of assuming that it's a global."""
day = date.today() - timedelta(days=N-x-1)
return day.strftime('%m%d')
def plotBar(data, color):
plt.bar(range(len(data)), data, align='center', color=color)
N = 30 # define the range that we want to look at
all, valid = getDataFromLast(N, timedelta(days=1)) # get the data
plotBar(all, "#4788d2") # plot both deleted and non-deleted data
plotBar(valid, "#0c3688") # plot only the valid data
plt.xticks(range(N), [format_date(i) for i in range(N)], size='small', rotation=30)
plt.grid(axis="y")
plt.show()
Оригинал:
Добре, това е моят опит за рефакторинг за вас. Blubber предложи да научите JS и MapReduce. Няма нужда, стига да следвате другите му предложения:създайте индекс в полето за време и намалете броя на заявките. Това е най-добрият ми опит за това, заедно с леко преработване. Имам обаче куп въпроси и коментари.
Започва след:
with my_mongodb() as m:
for i in range(30):
day = today - timedelta(days = i)
t1 = [m.data.find({"time": {"$gte": day, "$lt": day + timedelta(days = 1)}}).count()] + t1
t2 = [m.data.find({"deleted": 0, "time": {"$gte": day, "$lt": day + timedelta(days = 1)}}).count()] + t2
Вие правите заявка за mongoDB, за да намерите всички данни от всеки ден от последните 30 дни. Защо просто не използвате една заявка? И след като имате всички данни, защо просто не филтрирате изтритите данни?
with my_mongodb() as m:
today = date.today() # not sure why you were combining this with time(). It's the datetime representation of the current time.time()
start_date = today -timedelta(days=30)
t1 = m.find({"time": {"$gte":start_date}}) # all data since start_date (30 days ago)
t2 = filter(lambda x: x['deleted'] == 0, all_data) # all data since start_date that isn't deleted
Наистина не съм сигурен защо правите 60 заявки (30 * 2, една за всички данни, една за неизтритите). Има ли някаква конкретна причина да трупате данните ден след ден?
След това имате:
x = range(30)
N = len(x)
Защо не:
N = 30
x = range(N)
len(range(x)
е равно на x
, но отнема време за изчисляване. Начинът, по който го написахте първоначално, е малко... странен.
Ето моята идея, с промените, които предложих, направени по начин, който е възможно най-общ.
from datetime import datetime, date, time, timedelta
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from my_conn import my_mongodb
def getDataFromLast(delta):
""" Delta is a timedelta for however long ago you want to look
back. For instance, to find everything within the last month,
delta should = timedelta(days=30). Last hour? timedelta(hours=1)."""
m = my_mongodb() # what exactly is this? hopefully I'm using it correctly.
today = date.today() # was there a reason you didn't use this originally?
start_date = today - delta
all_data = m.data.find({"time": {"$gte": start_date}})
valid_data = filter(lambda x: x['deleted'] == 0, all) # all data that isn't deleted
return all_data, valid_data
def format_date(x, N, pos=None):
""" This is your format_date function. It now takes N
(I still don't really understand what it is, though)
as an argument instead of assuming that it's a global."""
day = date.today() - timedelta(days=N-x-1)
return day.strftime('%m%d')
def plotBar(data, color):
plt.bar(range(len(data)), data, align='center', color=color)
N = 30 # define the range that we want to look at
all, valid = getDataFromLast(timedelta(days=N))
plotBar(all, "#4788d2") # plot both deleted and non-deleted data
plotBar(valid, "#0c3688") # plot only the valid data
plt.xticks(range(N), [format_date(i) for i in range(N)], size='small', rotation=30)
plt.grid(axis="y")
plt.show()