Select Distinct with new object / anonymous type

503 views
Skip to first unread message

Alex Brown

unread,
Jul 6, 2012, 11:34:33 AM7/6/12
to mongodb...@googlegroups.com
I have a document in a collection called Results.

A Result class looks like:

public class Result
{
    public virtual int ResultId { get; set; }
    public virtual DateTime ResultDate { get; set; }
    public virtual string ResultVenue { get; set; }
    public virtual string DisciplineCode { get; set; }
    public virtual string DisciplineName { get; set; }
    public virtual int CompetitorId { get; set; }
    public virtual string CompetitorLastName { get; set; }
    public virtual string CompetitorFirstName { get; set; }
    public virtual string CompetitorTeamName { get; set; }
}

In my collection, there's around 1million documents.

I'm trying to retrieve a list of all the distinct DisciplineCode & DisciplineNames in the Result collection

My query looks like:

            var disciplines = _db.GetCollection<Result>.AsQueryable()
                .Select(d => new { d.DisciplineName, d.DisciplineCode })
                .Distinct()
                .ToList();


But, I get the error:

Unable to determine the serialization information for the expression: new __AnonymousType<String, String>(d.DisciplineName, d.DisciplineCode).


Annoying stack trace below:

Eventually, hoping to use a Discipline class instead of anonymous type - but that produced the same error.

Any suggestions??



[NotSupportedException: Unable to determine the serialization information for the expression: new __AnonymousType<String, String>(d.DisciplineName, d.DisciplineCode).] MongoDB.Driver.Linq.Utils.BsonSerializationInfoFinder.GetSerializationInfo(Expression node, Dictionary`2 serializationInfoCache) +182 MongoDB.Driver.Linq.Utils.BsonSerializationInfoHelper.GetSerializationInfo(Expression node) +40 MongoDB.Driver.Linq.SelectQuery.ExecuteDistinct(IMongoQuery query) +283 MongoDB.Driver.Linq.SelectQuery.Execute() +235 MongoDB.Driver.Linq.MongoQueryProvider.Execute(Expression expression) +114 MongoDB.Driver.Linq.MongoQueryable`1.GetEnumerator() +42 System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +315 System.Linq.Enumerable.ToList(IEnumerable`1 source) +58 IAAFProto.Web.Controllers.RecordsController.Index() in C:\Users\alex brown\Dropbox\Clients\Haymarket\IAAF\source\trunk\IAAFProto\Controllers\RecordsController.cs:19 lambda_method(Closure , ControllerBase , Object[] ) +96 System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +51 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +409 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +52 System.Web.Mvc.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() +127 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +436 System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +61 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +305 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +830 System.Web.Mvc.Controller.ExecuteCore() +136 System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +232 System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +39 System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +68 System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +44 System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +42 System.Web.Mvc.Async.WrappedAsyncResult`1.End() +141 System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +54 System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40 System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +61 System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +31 System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +56 System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +110 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8970061 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184


craiggwilson

unread,
Jul 6, 2012, 12:26:31 PM7/6/12
to mongodb...@googlegroups.com
Alex,
  Distinct can only be used for a single key, where you are using multiple keys, DisciplineCode and DisciplineName. See here for reference: http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct.

  If you change your code to use just DisciplineCode (.Select(r => r.DiscplineCode)), this works successfully.  I've file https://jira.mongodb.org/browse/CSHARP-522 to give a better error message.
Message has been deleted
Message has been deleted

Alex Brown

unread,
Jul 6, 2012, 12:54:14 PM7/6/12
to mongodb...@googlegroups.com
Thanks for your reply...

How can I achieve what I need to in that case?
ie- Select a list of distinct Discipline items from my Result collection?

Is that possible?
by Discipline items, i need to get DisciplineCode, DisciplineName etc...
(not just the code)

I don't have (nor intend to) a standalone "Discipline" collection

Surely, it must be?

craiggwilson

unread,
Jul 8, 2012, 4:11:15 PM7/8/12
to mongodb...@googlegroups.com
I'm afraid you will need a different collection to accomplish what you need (and still keep everything fast).  The alternative collection would likely store all the same information, just in a unique way.  You'd leave your existing collection.  The idea behind this is that you store your data in the way that is condusive to querying because you will likely be querying fare more often than you will be writing.  So, writing becomes more difficult, but reading is dead simple.

Alternatively, you could check out the new aggregate framework that is out now in 2.1.0 and will be stable in 2.2, due shortly.   http://docs.mongodb.org/manual/applications/aggregation/ 

Alex Brown

unread,
Jul 9, 2012, 6:00:29 AM7/9/12
to mongodb...@googlegroups.com
this seems like such legwork to do something so simple in other drivers...

I've managed to get it working in Mongo shell.
Using .group works.

Like so:

g1 = db.result.group({ 
    key: {DisciplineName:1, DisciplineCode:1}, 
    reduce: function(obj, prev) { if (!obj.hasOwnProperty("DisciplineName")) { 
        prev.DisciplineName = obj.DisciplineName; 
        prev.DisciplineCode = obj.DisciplineCode; 
    }}, 
    initial: { } 
});

That returns what I'm looking for.

Is there a way of translating this to use in the C# wrapper?

Alex Brown

unread,
Jul 9, 2012, 8:20:53 AM7/9/12
to mongodb...@googlegroups.com

Daniel Harman

unread,
Jul 9, 2012, 9:42:32 AM7/9/12
to mongodb...@googlegroups.com
Does that not fail on the keep everything fast criteria? 

Sent from my iPad

Alex Brown

unread,
Jul 9, 2012, 9:44:40 AM7/9/12
to mongodb...@googlegroups.com
in what way?
as per craigs comment, on not using mapreduce for "realtime" queries?
then yeah.. i guess.

i suppose i'll have to persist the output of this as a separate collection and query that eventually
but for now is ok.
Reply all
Reply to author
Forward
0 new messages