Banner_Etool

Mi nueva tabla para verano

Por: Emilio Torrens  /  En: ,

20 litros mas que este año no quiero estar esperando viento, quiero salir cada vez que suba ;)

rocket_135_2013

Ahorrando espacio con MongoDB

Por: Emilio Torrens  /  En: , ,

mongodbAl ser una base de datos libre de esquema cada documento guarda su esquema, eso quiere decir que los nombres de los campos se guardan en cada documento, en el caso de MongoDB ahorrar espacio también significa ahorrar RAM ya que intenta mantener los datos en memoria.

Hay 2 maneras sencillas de hacer que los documentos sean mas pequeños, utilizar nombres de campos cortos y no guardar valores por defecto, estas dos maneras nos valen usemos el Driver que usemos aunque usare el de C# como ejemplo.

1- Utilizar nombres de campos cortos

El Driver de C# nos facilita mucho este trabajo ya que tiene un atributo en el que podemos decirle con que nombre queremos guardar cada propiedad en la base de datos, el se encarga de mapear los nombres y además te hace la conversión cuando Filtras, siempre que uses el QueryBuilder Tipado, lo mismo a la hora de usar el SetFields o el SetSortOrder, hay que usar el IMongoFields y el IMongoSort tipado para que el Driver haga la conversión de nombres.

Por ejemplo creamos esta clase con los nombres normales mapeados a nombres cortos:

public class Person 
{ 
        [BsonElement("n")] 
        public string Name { get; set; }
 
        [BsonElement("a")] 
        public int Age { get; set; }
 
        [BsonElement("ac")] 
        public bool Active { get; set; } 
}

Estas serian las Querys:

//Esto funcionaria 
var result = col.Find(Query<Person>.EQ(p => p.Name, "Juanito")); 
result = col.Find(Query.EQ("n", "Juanito"));
 
//Esto No Funcionaria 
result = col.Find(Query.EQ("Name", "Juanito"));

En resumen, si usamos nombres de campos cortos debemos usar siempre los Builders tipados que nos ofrece el Driver de C#.

2- No guardar valores por defecto

Siguiendo con la clase anterior, si la mayoría de nuestras Personas van a estar con Active a True, podemos ahorrarnos guardar ese campo y guardarlo solo cuando este a False:

[BsonElement("ac")] 
[BsonDefaultValue(true)] 
[BsonIgnoreIfDefault]    
public bool Active { get; set; }

Con este código el campo Active solo se guardara en la base de datos cuando sea false, el Driver al cargar un documento que no tenga este campo nos lo devolverá como True.

Esta segunda opción es mas difícil de implementar por el tema de los filtros ya que, hasta el momento, el driver no lo contempla, por ejemplo para filtrar todas las personas activas tendríamos que filtras los activos o los que no tienen ese campo:

var result = col.Find(Query.Or(Query<Person>.EQ(p => p.Active, true),
                               Query<Person>.NotExists(p=>p.Active)));

Aunque este caso es sencillo, si usamos valores por defecto en integers, doubles, fechas, hay que controlar los mayor que, menor que etc.

En MongoMapper para .NET existe un objeto MongoQuery que controla estos dos casos, convierte los nombres de los campos sin tipar y controla el tema de los DefaultValue a la hora de filtrar, por si le queréis pegar un vistazo Sonrisa

MongoDB March Madness Hackathon

Por: Emilio Torrens  /  En: , , , , ,

La gente de 10gen ha organizado un hackathon de un mes de duración para Grupos de Usuarios de MongoDB, el MongoDB March Madness.

Desde ”Mallorca MUG” participamos con este proyecto:

image

Si te interesa al hackaton únete al grupo que la semana que viene haremos un meetup para organizar las tareas Sonrisa

MongoMapper.NET

Por: Emilio Torrens  /  En: , , , ,

mongomapper_grandeAcabo de subir a la rama de producción los cambios de master

Lamentablemente he tenido que romper compatibilidad en algunas cosas.

-He cambiado todo el sistema de búsquedas,  he quitado el Finder y todos los métodos estáticos de la clase MongoMapper, a cambio he metido una clase nueva, MongoMapperCollection, que es la que se usara en las búsquedas:

var col = new MongoMapperCollection<Country>();
 
col.Find().SetLimit(1);     
Assert.AreEqual(1, col.Count);
Assert.AreEqual(3, col.Total);     
 
col.Find().SetLimit(3).SetSortOrder("Name");
Assert.AreEqual(3, col.Count);
Assert.AreEqual(3, col.Total);
 
col.Find(Query<Country>.EQ(C => C.Code, "NL"));
Assert.AreEqual("NL",col.First().Code);
Assert.AreEqual("NL", col.Last().Code);
 
foreach (Country country in col)
{}

También puedes heredar tu clase de MongoMapperCollection y usarla ya “Tipada”

public class CountryCollection: MongoMapperCollection<Country>
{}
 
var col = new CountryCollection();
 
col.Find().SetLimit(1);     
Assert.AreEqual(1, col.Count);
Assert.AreEqual(3, col.Total);     
 
col.Find().SetLimit(3).SetSortOrder("Name");
Assert.AreEqual(3, col.Count);
Assert.AreEqual(3, col.Total);
 
col.Find(Query<Country>.EQ(C => C.Code, "NL"));
Assert.AreEqual("NL",col.First().Code);
Assert.AreEqual("NL", col.Last().Code);
 
foreach (Country country in col)
{}

-La configuración también ha cambiado, como en cada versión están sacando cosas nuevas era inmantenible, la he cambiado para definir una Url con todas las configuraciones, ahora queda una cosa así:

<MongoMapperConfig>
    <Server Url="mongodb://127.0.0.1" />
    <Database Name="TestDotNET" />
    <Context Generated="true" MaxDocumentSize="8" ExceptionOnDuplicateKey="true" EnableOriginalObject="true"
             UseIncrementalId="true" UseChidlsIncrementalId="false" />
    <CollectionConfig>
      <add Name="TestConf1">
        <Server Url="mongodb://host1:27017,host2:27017,host3:1234/?readPreference=primaryPreferred;w=2" />
        <Database Name="Conf1" />
        <Context Generated="true" MaxDocumentSize="8" ExceptionOnDuplicateKey="true" EnableOriginalObject="true"
                 UseIncrementalId="false" UseChidlsIncrementalId="true" />
      </add>
      <add Name="Person">
        <Server Url="mongodb://127.0.0.1" />
        <Database Name="TestDotNETPerson" />
        <Context Generated="true" MaxDocumentSize="8" ExceptionOnDuplicateKey="true" EnableOriginalObject="true"
                 UseIncrementalId="true" UseChidlsIncrementalId="false" />
      </add>
    </CollectionConfig>
  </MongoMapperConfig>

- He cambiado el nombre al campo que controla la versión del Documento de MongoMapperDocumentVersion a m_dv y el MongoMapper_Id a m_id, el Id no pasa nada ya que internamente se guarda como _id,  pero el otro si, para colecciones con datos tendrás que usar el rename:

db.collection_name.update ( {}, { $rename : { "MongoMapperDocumentVersion" : "m_dv" }, false, true } );

Ademas necesita la versión >= 1.7 del Driver, ya que ellos también han hecho muchos cambios.

Otros cambios son:

  • Implementado ISupportInitialize para el tema de OriginalObject, ya no es necesario usar la versión modificada del Driver para esto
  • Posibilidad de susbcribise a eventos en el BeginInit y EndInit del ISupportInitialize, son OnObjectInit y OnObjectComplete
  • Añadida propiedad “ExtraElements” donde se recogerán los valores de los propiedades que no estén definidas en la clase.
  • Eliminado el <T> en todos los métodos no estáticos de la clase base, ahora queda mejor el código.
  • Eliminados todos los métodos de búsqueda que recibían una expresión, como expone la colección se puede usar el LINQ del Driver.
  • Update a la versión 1.7 del Driver, MongoClient, WriteConcern y todos esos cambios.

Esta versión esta ahora en master y en Producción.

https://github.com/emiliotorrens/MongoMapper.NET

Cualquier cosa email me o fork.

Mallorca MUG: MongoDB y .NET

Por: Emilio Torrens  /  En: , , , , , ,

Aquí dejo la presentación de la charla sobre MongoDB y .NET en el “Mallorca MongoDB User Group”