2011-04-19 13 views
15

Estamos planeando utilizar MongoDB para almacenar grandes cantidades de datos analíticos, como vistas y clics. No estoy seguro de la mejor manera de estructurar los documentos dentro de MongoDB para ayudar a consultar y reducir el tamaño de la base de datos.MongoDB Enfoques para almacenar grandes cantidades de datos de métricas/análisis

Necesitamos registrar acciones contra un nombre de página, cliente y el tipo de acción. Idealmente, necesitamos estadísticas que bajen al nivel año/mes/día/hora, no necesitamos ni nos importan las vistas por segundo o minuto. Si bien esta estructura de documentos se ve bien, soy consciente de que 100 visitantes generarían 100 documentos nuevos.

{ 
    "_id" : ObjectId("4dabdef81a34961506040000"), 
    "pagename" : "Hello", 
    "action" : "view", 
    "client" : "client-name", 
    "time" : Date("Mon Apr 18 07:49:28 2011") 
} 

¿Hay mejor manera práctica de hacer esto, ya sea usando $inc o Capped Collections?

Respuesta

15

respuesta Actualizado

Hacked juntos en la consola mongo:

use pagestats; 

// a little helper function 
var pagePerHour = function(pagename) { 
    d = new Date(); 
    return { 
     page : pagename, 
     year: d.getUTCFullYear(), 
     month: d.getUTCMonth(), 
     day : d.getUTCDate(), 
     hour: d.getUTCHours(), 
    } 
} 

// a pageview happened 
db.pagestats.update(
    pagePerHour('Hello'), 
    { $inc : { views : 1 }}, 
    true); //we want to upsert 

// somebody tweeted our page twice! 
db.pagestats.update(
    pagePerHour('Hello'), 
    { $inc : { tweets : 2 }}, 
    true); //we want to upsert 

db.pagestats.find(); 
// { "_id" : ObjectId("4dafe88a02662f38b4a20193"), 
// "year" : 2011, "day" : 21, "hour" : 8, "month" : 3, 
// "page" : "Hello", 
// "tweets" : 2, "views" : 1 } 

// 24 hour summary 'Hello' on 2011-4-21 
for(i = 0; i < 24; i++) { 
    //careful: days (1-31), month (0-11) and hours (0-23) 
    stats = db.pagestats.findOne({ page: 'Hello', year: 2011, month: 3, day : 21, hour : i}) 
    if(stats) { 
     print(i + ': ' + stats.views + ' views') 
    } else { 
     print(i + ': no hits') 
    }; 
} 

Dependiendo de qué aspectos desea realizar un seguimiento que podría considerar la adición de más colecciones (por ejemplo, una colección para el seguimiento centrado en el usuario) Espero que ayude.

Ver también

Blogpost about Analytics Data

+0

Interesante, ¿cómo sería la sintaxis de find() si quisiera mostrar un conteo de vistas para 'Hola' por cada hora del último día? – Tom

+0

.. entonces esta solución no sería exactamente ideal. Pero espere, publicaré una actualización. – Matt

+0

Mientras tanto, es posible que desee echar un vistazo a http://cookbook.mongodb.org/patterns/unique_items_map_reduce/ – Matt

1

yo no me preocuparía demasiado por el espacio, Mongo puede escalar casi infinitamente en ese sentido, la adición de más espacio sería razonablemente barato.

Una cosa a tener en cuenta es el hecho de que si sigue actualizando un documento, su tamaño crecerá, lo que significa que, con el tiempo, Mongo tendrá que encontrar un nuevo lugar para él en el índice. Si tiene una gran cantidad de documentos que se actualizan y aumentan de tamaño, Mongo tendrá que copiar estos documentos por mucho, esto puede ralentizar significativamente las cosas. Por supuesto, todo esto depende de la cantidad de tráfico que está esperando.

Según mi experiencia, vaya con un formato de documento simple donde no necesite actualizar los documentos, puede complicar su consulta más adelante, pero puede usar map/reduce para obtener la información que desee independientemente de su estructura del documento (la reducción del mapa es muy flexible si se cuenta con suficiente experiencia como para hacer cualquier cosa).

Cuestiones relacionadas