sql >> Base de Datos >  >> NoSQL >> MongoDB

Visualización de estadísticas de datos de Mongodb usando matplotlib

ACTUALIZAR:

Fundamentalmente entendí mal el problema. Felix estaba consultando mongoDB para averiguar cuántos elementos caían en cada rango; por lo tanto, mi enfoque no funcionó, porque estaba tratando de pedirle a mongoDB for Los artículos. Felix tiene una gran cantidad de datos, por lo que esto es completamente irrazonable.

Felix, aquí tienes una función actualizada que debería hacer lo que quieras:

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 es el "paso" para mirar hacia atrás. Por ejemplo, si quisiéramos ver las últimas 12 horas, configuraría quantum = timedelta(hours=1) y num = 12 .Un ejemplo de uso actualizado donde obtenemos los últimos 30 días sería:

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

Original:

Muy bien, este es mi intento de refactorización para ti. Blubber ha sugerido aprender JS y MapReduce. No es necesario siempre que siga sus otras sugerencias:cree un índice en el campo de tiempo y reduzca la cantidad de consultas. Este es mi mejor intento en eso, junto con una ligera refactorización. Aunque tengo un montón de preguntas y comentarios.

A partir de:

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

Está realizando una solicitud mongoDB para encontrar todos los datos de cada día de los últimos 30 días. ¿Por qué no usas solo una solicitud? Y una vez que tenga todos los datos, ¿por qué no simplemente filtrar los datos eliminados?

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

Realmente no estoy seguro de por qué estabas haciendo 60 solicitudes (30 * 2, una para todos los datos, otra para los no eliminados). ¿Hay algún motivo en particular por el que acumulaste los datos día a día?

Entonces, tienes:

x = range(30)
N = len(x)

Por qué no:

N = 30
x = range(N)

len(range(x) es igual a x , pero toma tiempo para calcular. La forma en que lo escribiste originalmente es un poco... rara.

Esta es mi solución, con los cambios que sugerí realizados de la manera más general posible.

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