简体   繁体   中英

Mapping subclasses / embedded to single flat document with MongoDB C# driver

I'm developing an app that has a model using race results / times etc..
I've got a model that looks something like:

public class Competitor
{
    public int ID { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
}

public class Event
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
}

public class Result
{
    public int ID { get; set; }
    public decimal ResultTime { get; set; }
    public Competitor Competitor { get; set; }
    public Event Event { get; set; }
}

I'm planning on flattening this for storing into mongo db, like this:

public class ResultSchemaExample
{
    public int CompetitorID { get; set; }
    public string CompetitorName { get; set; }
    public DateTime CompetitorDateOfBirth{ get; set; }
    public int EventID { get; set; }
    public string EventName { get; set; }
    public string EventDescription { get; set; }
    public int ResultID { get; set; }
    public decimal ResultTime { get; set; }
}

My concern is, this is going to make querying further up a little harder?
Is there a way I can classMap this to make it easier?

So I could do queries like:

var query =
    collection.AsQueryable<Result>()
    .Where(r => r.Name == "Alex");

And it would query my underlying, flat (non embedded) data to return instances of Result?

Is this possible?

Or, shall I just use my ResultSchemaExample across my app?

You could always have a composition class like this and store this in mongodb.

public class RaceResults
{
  public Competitor Competitor { get; set;}
  public Event Event { get; set;}
  public Result Result { get; set;}
}

Your query would then look like this:

var query = collection.AsQueryable<RaceResults>().Where(r => r.Result.Name == "Alex");

However, I would probably suggest a different schema entirely... Starting at your domain, I'm sure there is a rule that states that you cannot have a Result without an Event. That would lead me to design your domain slightly different; more like this:

public class Event
{
  public string Name { get; set; }
  public string Description { get; set; }
  public IList<Result> Results { get; set; }
}

public class Result
{
  public Competitor Competitor { get; set; }
  public TimeSpan ResultTime { get; set; }
}

public class Competitor
{ ... }

With this schema, you would have only 1 collection in mongodb: events. Each event would contain all the data it needs. Correlating competitor's results across events would be fairly simple as well because mongodb supports querying inside arrays and documents. So the below query would get all the events where competitor 42 competed:

var collection = db.GetCollection<Event>("events");
var query = Query.EQ("Results.Competitor.Id", 42);
var events = collection.Find(query);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM