1. Mallorca #MongoDB User Group
http://www.meetup.com/Mallorca-MongoDB-User-Group/
MongoDB y .NET
@emiliotorrens | www.emiliotorrens.com
2. Agenda
El Driver de C#
Usando el Driver de C#:
MongoClient
BsonDocument
Serialización
Query Builder
Update Builder
LINQ
Ejemplos:
Definir y trabajar con una clase
Búsquedas
Aggregation Framework
3. El Driver de C#
El driver de C# es uno de los drivers oficiales que están soportados por la gente de 10gen.
La versión actual, la 1.7, utiliza el Framework 3.5 y es totalmente compatible con Mono.
Es Open Source y esta alojado en GitHub:
https://github.com/mongodb/mongo-csharp-driver
Esta disponible como paquete de NuGet:
http://nuget.org/packages/mongocsharpdriver/
Hay un grupo de discusión especifico para este Driver:
https://groups.google.com/forum/?fromgroups#!forum/mongodb-csharp
Hay un proyecto en el JIRA de MongoDB para poner y hacer seguimiento de bugs/mejoras:
https://jira.mongodb.org/browse/CSHARP
Su documentación esta alojada en el sitio de MongoDB:
http://docs.mongodb.org/ecosystem/drivers/csharp/
4. Usando el Driver de C#
Al ser un lenguaje estático no podemos escribir Json o diccionarios como haríamos en ruby o python, para suplirlo el
Driver lleva un Objeto “BsonDocument” y una serie de “Builders”.
Para usar el Driver tan solo debemos descargar las dll del Driver (MongoDB.Bson.dll y MongoDB.Driver.dll) y
añadirlas como referencia a nuestro proyecto.
Como mínimo será necesario añadir estos 2 using:
using MongoDB.Bson;
using MongoDB.Driver;
Para usar los builders:
using MongoDB.Driver.Builders;
Para controlar la Serilización:
using MongoDB.Bson.Serialization.Attributes;
Para usar LINQ:
using MongoDB.Driver.Linq;
5. Usando el Driver de C#: MongoClient
MongoClient es la clase cliente, la que tendrá toda la configuración y desde la que accederemos al server, las bases
de datos y las colecciones.
Crear una instancia de la clase y acceder a los datos es tan fácil como:
var connectionString = "mongodb://db1.example.net,db2.example.net:2500/?replicaSet=test";
var client = new MongoClient(connectionString);
var server = client.GetServer();
var database = server.GetDatabase(“database_name");
var collection = database.GetCollection<MyClass>(“MyClassCollection");
Tiene una sobrecarga para pasarle la clase MongoClientSettings, yo creo que es mucho mas fácil usar la connection
string ya que le puedes pasar las mismas opciones que a la clase de settings.
Puedes ver aquí las opciones de la string de conexión:
http://docs.mongodb.org/manual/reference/connection-string/
6. Usando el Driver de C#: MongoCollection
MongoCollection es la clase de los datos, es la que usaremos para buscar y escribir en la base de datos
Para instanciarla:
var collection = database.GetCollection<MyClass>(“MyClassCollection");
De los métodos que contiene esta clase estos son los que usaremos para leer y escribir datos:
Insert, InsertBatch, Save, Update, Remove, FindAndModify, FindAndRemove, FindAll, Find, FindOne, FindOneById.
Tiene otros métodos en los que no entraremos en detalle como MapReduce, GeoSearch, Gestion de Indices,
Aggregation etc.
Puedes ver toda la documentación aquí:
http://api.mongodb.org/csharp/current/html/6d5bbe8e-46f4-087f-8e83-06297634ed40.htm
7. Usando el Driver de C#: BsonDocument
BsonDocument es el objeto que utilizaremos para escribir BSON en nuestro código, es un modelo de objetos en
memoria que representa un documento BSON.
Podemos usarlo para escribir y leer datos en la base de datos::
MongoCollection<BsonDocument> books = database.GetCollection<BsonDocument>("books");
BsonDocument book = new BsonDocument {
{ "author", "Ernest Hemingway" },
{ "title", "For Whom the Bell Tolls" }
};
books.Insert(book);
Aunque yo creo que es mejor usar nuestras clases:
MongoCollection<Book> books = database.GetCollection<Book>("books");
Book book = new Book {
Author = "Ernest Hemingway",
Title = "For Whom the Bell Tolls"
};
books.Insert(book);
8. Usando el Driver de C#: BsonDocument
Algunas veces será imprescindible usar BsonDocument, pero yo solo lo he tenido que usar obligatoriamente para las
operaciones del “Aggregation Framework”:
operations = new[]{
new BsonDocument {
{
"$group", new BsonDocument{ { "_id" , "$Name" } , {"Total" , new BsonDocument{ {"$sum","$Age"} } } }
}
}
};
result = collection.Aggregate(operations);
Al final veremos un ejemplo.
9. Usando el Driver de C#: Serialización
Esta es una parte muy importante del Driver ya MongoDB es una base de datos libre de esquema y es aquí donde
controlaremos el modelo de datos.
Por defecto el Driver hace un auto mapeo de nuestras clases a Documentos simplemente campo a campo, pero el
Driver nos da herramientas para controlarlo.
Hay dos maneras de hacerlo usando BsonClassMap.RegisterClassMap o usando Atributos e Interfaces, yo creo que
es mejor usar atributos e interfaces.
A continuación veremos los mas habituales, puedes ver todas las posibilidades aquí:
http://docs.mongodb.org/ecosystem/tutorial/serialize-documents-with-the-csharp-driver/
10. Usando el Driver de C#: Serialización
Cualquier propiedad que no sea de solo lectura de nuestra clase automáticamente será mapeada, pero podemos
usar BsonElement para:
• Cambiar el nombre con el que se guarda en el Documento.
• Forzar a que una propiedad de solo lectura se guarde.
• Especificar el orden de Serialización.
public class MyClass {
[BsonElement("sp", Order = 1)]
public string SomeProperty { get; set; }
}
BsonIgnore o BsonIgnoreIfNull sirven para hacer que el mapeo ignore una propiedad o la ignore solo cuando es null:
public class MyClass {
[BsonIgnore]
public string SomeProperty { get; set; }
}
11. Usando el Driver de C#: Serialización
BsonId sirve para indicar que campo será el _id del documento, además le podemos indicar como se generara ese
_id, el Driver lleva varios generadores incluidos, si no nos bastan, podemos escribir el nuestro:
public class MyClass {
[BsonId(IdGenerator = typeof(GuidGenerator))]
public Guid Id { get; set; }
}
De los generadores incluidos los que se usan habitualmente son:
• BsonObjectIdGenerator para BsonObjectId.
• GuidGenerator para Guid.
• ObjectIdGenerator para ObjectId.
• StringObjectIdGenerator para ObjectId como strings.
Aqui hay un ejemplo de uno propio donde el _id es long y tiene la posibilidad de que sea incremental:
https://github.com/emiliotorrens/MongoMapper.NET/blob/master/EtoolTech.MongoDB.Mapper/Core/MongoMapp
erIdGenerator.cs
12. Usando el Driver de C#: Serialización
BsonDefaultValue sirve para indicar el valor por defecto de una propiedad:
public class MyClass {
[BsonDefaultValue("abc")]
public string SomeProperty { get; set; }
}
Además podemos ignorar la propiedad si tiene el valor por defecto:
public class MyClass {
[BsonDefaultValue("abc")]
[BsonIgnoreIfDefault]
public string SomeProperty { get; set; }
}
Aunque no parezca útil ignorar si tiene valor por defecto eso nos permite ahorrar espacio en la base de datos.
13. Usando el Driver de C#: Serialización
Podemos escribir nuestro serializador y asignárselo a una propiedad con BsonSerializer :
public class MyClass {
public ObjectId Id { get; set; }
[BsonSerializer(typeof(MyCustomStringSerializer))]
public string X { get; set; }
}
Los DateTime se guardan en UTC podemos hacer que el serializador convierta a local cuando nos lo muestre y a UTC
cuando lo guarde con BsonDateTimeOptions:
public class MyClass {
[BsonDateTimeOptions(Kind = DateTimeKind.Local)]
public DateTime AppointmentTime { get; set; }
}
Ademas con BsonDateTimeOptions podemos hacer que ignore la hora
public class MyClass {
[BsonDateTimeOptions(DateOnly = true)]
public DateTime DateOfBirth { get; set; }
}
14. Usando el Driver de C#: Serialización
Normalmente la Serialización no se preocupa si tienes campos de mas en la clase, simplemente quedan a null o en
su valor por defecto, si quieres que lance una excepción en el caso de que ese campo no este en el Documento
tienes que usar BsonRequired:
public class MyClass {
[BsonRequired]
public string X { get; set; }
}
15. Usando el Driver de C#: Serialización
Tenemos disponibles opciones de Serialización a nivel de clase e incluso podemos escribir nuestro propio
serializador, cosa que no recomiendo, el del Driver va bien y es rápido, no hay que reinventar.
Podemos controlar que hacer con los elementos extras, campos que están en los documentos y no están en la clase,
podemos ignorarlos con BsonIgnoreExtraElements:
[BsonIgnoreExtraElements]
public MyClass {
}
Tambien podemos definir una propiedad con el atributo BsonExtraElements para que nos deje alli todos los campos
extras:
public MyClass {
[BsonExtraElements]
public IDictionary<string, object> CatchAll { get; set; }
}
Además podemos poner código pre y post Serialización en la clase ya que el driver soporta ISupportInitialize:
https://jira.mongodb.org/browse/CSHARP-387
16. Usando el Driver de C#: Query Builder
Este builder es el que usaremos para construir las sentencias de búsqueda de datos, soporta todos los operadores
de búsqueda de MongoDB GT, GTE, In, LT, LTE, Near, NE, And, Or ..
Utilizar el builder es realmente sencillo:
var persons = collection.Find(Query<Person>.EQ(p=>p.Age, 25));
Podemos ir anidando los operadores e indicar el orden del resultado:
var persons = collection.Find(Query.And(Query.Or(Query.EQ("Age", 25),
Query.EQ("Age", 26)),Query.Matches("Name",new BsonRegularExpression("Juan")))).SetSortOrder("Age");
La respuesta es un cursor al que le podemos indicar que campos queremos traer, skip, limit … :
var persons = collection.Find(Query.EQ("Childs.Age", 5)).SetFields(“Name").SetSkip(1).SetLimit(1);
Aquí podéis encontrar una referencia de selects SQL a Querys MongoDB:
http://docs.mongodb.org/manual/reference/sql-comparison/#select
Y aquí algunos ejemplos:
https://github.com/emiliotorrens/mongodb-drivers-samples/blob/master/csharp/mongodb-samples/Querying.cs
17. Usando el Driver de C#: Update Builder
Este builder es el que usaremos para construir las sentencias para modificar datos en la “parte del servidor” es decir,
sin mandar todo el Documento de nuevo, o para modificaciones a mas de un Documento.
Soporta todos los operadores de MongoDB:
http://docs.mongodb.org/manual/applications/update/#update-operators
La respuesta de las operaciones de escritura es la clase WriteConcernResult, contiene los resultados, documentos
afectados, errores etc.
La sintaxis es muy sencilla, es pasar el filtro de documentos a modificar, la operación y las opciones:
var result = collection.Update(Query.EQ("_id", Id), Update<Person>.Set(x=>x.Name, "Name2").Inc(x=>x.Age, 1));
if (result.HasLastErrorMessage) throw new Exception(result.ErrorMessage);
var result = collection.Update(Query.EQ("Age",45), Update.PushWrapped("Childs", new Child { Name = "child 3",
Age = 3 }), UpdateFlags.Multi);
Aquí podéis encontrar una referencia de updates SQL a Querys MongoDB:
http://docs.mongodb.org/manual/reference/sql-comparison/#update-records
18. Usando el Driver de C#: LINQ
El Driver tiene soporte para linq simplemente llamando al método AsQueryable de la colección podremos hacer
consultas linq:
Agregamos el using:
using MongoDB.Driver.Linq;
Y hacemos las consultas;
var query =
from p in collection.AsQueryable<Person>()
where p.Age == 36
select p;
foreach (var person in query)
{}
Aquí puedes ver la lista de las operaciones soportadas:
http://docs.mongodb.org/ecosystem/tutorial/use-linq-queries-with-csharp-driver/
19. Usando el Driver de C#: Ejemplos
Definir y trabajar con una clase
https://github.com/emiliotorrens/mongodb-drivers-samples/blob/master/csharp/mongodb-samples/Person.cs
https://github.com/emiliotorrens/mongodb-drivers-samples/blob/master/csharp/mongodb-samples/Simple.cs
Búsquedas
https://github.com/emiliotorrens/mongodb-drivers-samples/blob/master/csharp/mongodb-samples/Querying.cs
Aggregation Framework
https://github.com/emiliotorrens/mongodb-drivers-samples/blob/master/csharp/mongodb-samples/Aggregation.cs
20. Próximos Meetups
• Poner MongoDB en Producción
• Objects Mappings para MongoDB
• MongoDB y Ruby on Rails
21. Mallorca #MongoDB User Group
http://www.meetup.com/Mallorca-MongoDB-User-Group/
Gracias por venir ;)
@emiliotorrens | www.emiliotorrens.com