2010-10-04 5 views
11

Estamos haciendo un pequeño aumento en Mongo DB para nuestro proyecto C# .NET para ver si es adecuado para nosotros, y me he encontrado con un pequeño problema con el controlador mongodb-csharp de samus que no estoy seguro de cómo para implementar.mongodb-csharp driver: cómo guardar una propiedad como referencia en lugar de incrustada?

Dado el siguiente modelo simplificado:

public class Campaign 
{   
    public string Name { get; set; } 
    public IEnumerable<Placement> Placements { get; set; } 
} 

public class Placement 
{ 
    public string Name { get; set; } 

    //this should be a reference rather than included in the collection 
    public Site Site { get; set; } 
} 

//this should be its own collection, and not embedded anywhere 
public class Site 
{ 
    public string Name { get; set; } 
} 

Estamos tratando de averiguar, ya que las observaciones anteriores sugieren, cómo ahorrar sitio como un tipo referenciado en lugar de incrustada en la colocación. El sitio es su propia colección de alto nivel que cambia independientemente de cada Campaña.

Idealmente, me gustaría hacer esto usando el MongoConfigurationBuilder en lugar de tener que modificar mis POCO. Simplemente no puedo encontrar ninguna documentación sobre cómo se logra esto.

Tenía la esperanza de que sería tan fácil como:

var config = new MongoConfigurationBuilder(); 

config.Mapping(mapping => 
{ 
    //maybe some more configuration here? 
    mapping.Map<Site>(); 
    mapping.Map<Campaign>(); 
}); 

Pero que sigue siendo la incorporación de sitios cuando se utiliza el siguiente código:

var db = mongo.GetDatabase("foo"); 

var campaignCollection = db.GetCollection<Campaign>(); 
var siteCollection = db.GetCollection<Site>(); 

var firstSite = new Site{Name = "first site"}; 
var secondSite = new Site{Name = "second site"}; 

var firstCampaign = new Campaign 
{ 
    Name = "first campaign", 
    Placements = new List<Placement> 
    { 
     new Placement{Name = "first placement", Site = firstSite}, 
     new Placement{Name = "second placement", Site = secondSite} 
    } 
}; 

siteCollection.Save(firstSite); 
siteCollection.Save(secondSite); 

campaignCollection.Save(firstCampaign); 

Esto nos está dando:

{ "_id" : ObjectId("4ca9f1db54730000000010cb"), 
    "Name" : "first campaign", 
    "Placements" : [ 
    { 
     "Name" : "first placement", 
     "Site" : { "Name" : "first site" } 
    }, 
    { 
     "Name" : "second placement", 
     "Site" : { "Name" : "second site" } 
    } 
    ]} 

{ "_id" : ObjectId("4ca9f1db54730000000010c9"), "Name" : "first site" } 
{ "_id" : ObjectId("4ca9f1db54730000000010ca"), "Name" : "second site" } 

Considerando que queremos algo más como:

{ "_id" : ObjectId("4ca9f1db54730000000010cb"), 
    "Name" : "first campaign", 
    "Placements" : [ 
    { 
     "Name" : "first placement", 
     "Site" : ObjectId("4ca9f1db54730000000010c9") 
    }, 
    { 
     "Name" : "second placement", 
     "Site" : ObjectId("4ca9f1db54730000000010ca") 
    } 
    ]} 

{ "_id" : ObjectId("4ca9f1db54730000000010c9"), "Name" : "first site" } 
{ "_id" : ObjectId("4ca9f1db54730000000010ca"), "Name" : "second site" } 

No estoy seguro de si ese es el documento exacto con el que terminaríamos, pero entiendes el punto.

Siento que me falta algo obvio, pero sin una mejor documentación sobre este aspecto del conductor, estoy disparando en la oscuridad. Incluso examiné las pruebas en la fuente y no pude resolverlo.

¿Alguien sabe cómo hacer esto? ¿Es posible?

Respuesta

9

Para ello, debe usar DBRef.

Para hacer esto en C#, usted tiene que cambiar su clase de campaña como ésta

public class Campaign 
{   
    public string Name { get; set; } 
    public List<DBRef> Placements { get; set; } 
} 

e insertar el documento de referencia como éste

List<DBRef> refList = new List<DBRef>() {firstSite,secondSite }; 


var firstCampaign = new Campaign 
{ 
    Name = "first campaign", 
    Placements = refList 
}; 

campaignCollection.Save(firstCampaign); 

No he probado el código, pero esto da la pista de cómo lograr esto.

+3

Esto funcionó gracias, aunque, lo que podría hacer en lugar de esto es simplemente usar un Oid. DBRef es bastante voluminoso, y todo lo que está usando en este caso es obtener la identificación para que pueda retirar el sitio. – mrdowns

+0

DBRefs no se puede usar en la canalización de agregación, así que hay un doble problema aquí en caso de que vaya por esa ruta ...;) – ostati

+0

¿Puede poner un ejemplo sobre cómo hacer un filtro simple en una lista de refs? Ej: ~ var filter = Constructores .Filter.In (c => c.Placements, listOfSiteIds); – Misi

Cuestiones relacionadas