I am having difficulties getting a map / reduce operation to work. I'm a hobbyist with C#, so probably it is partly due to my lack of experience with lambda's and linq to thoroughly analyse and understand the cause (what is an object create expression) leading to the error.
The code compiles perfectly, but when executed it throws an exception and I don't understand what part is not correct.
When I disable the reduce operation the error remains, so I assume it has to do with the Map part.
RavenDB version is: RavenDB-Build-573
This is the exception: System.InvalidOperationException: Variable initializer select must have a lambda expression with an object create expression
And I provide RavenDB with the index like this:
IndexCreation.CreateIndexes(typeof(FullTree).Assembly, store);
The Entity object is a simple class, featuring an int Id, and an int ParentId.
This is the map / reduce part:
public class FullTreeObject
{
public int Id { get; set; }
public int Count { get; set; }
public int ParentId { get; set; }
}
public class FullTree : AbstractIndexCreationTask<Entity,FullTreeObject>
{
public FullTree()
{
Map = entities => from entity in entities
let ids = new object[]
{
new { entity.Id, Count = 0,
entity.ParentId },
new { Id = entity.ParentId, Count
= 1, ParentId = (string)null}
}
from id in ids
select id;
Reduce = results => from result in results
group result by result.Id into g
let parent = g.FirstOrDefault(x =>
x.ParentId != null)
select new
{
Id = g.Key,
Count = g.Sum(x => x.Count),
ParentId = parent ==
(object)null ? (object)null : parent.ParentId
};
}
}
Hope someone can provide me with some clues. Thanks in advance.
--
In reaction to the input I've modified the map/reduce implementation. RavenDB requires map and reduce output the same type but to be honest, this can't be right since I'm outputing values of the entity object, and not those aquired in the array. But I cannot reach those values with intellisense.
The index is created in the RavenDB studio, but no results are returned so I can assume my implementation is faulty.
public class FullTree : AbstractIndexCreationTask<Entity,FullTreeObject>
{
public FullTree()
{
Map = entities => from entity in entities
let ids = new object[]
{
new { entity.Id, Count = 0, entity.ParentId },
new { Id = entity.ParentId, Count = 1, ParentId = (string)null}
}
from id in ids
select new {
entity.Id,
Count = 1,
entity.ParentId
};
Reduce = results => from result in results
group result by result.Id into g
let parent = g.FirstOrDefault(x => x.ParentId != null)
select new
{
Id = g.Key,
Count = g.Sum(x => x.Count),
ParentId = parent == (object)null ? (object)null : parent.ParentId
};
}
}
Update on Build 601:
public class FullTree : AbstractIndexCreationTask<Entity, FullTree.ReduceResult>
{
public class ReduceResult
{
public int Id { get; set; }
public int Count { get; set; }
public int ParentId { get; set; }
}
public FullTree()
{
Map = entities => from entity in entities
let items = new[]
{
new { Id = (int) entity.Id, Count = (int) 0, ParentId = (int) entity.ParentId },
new { Id = (int) entity.ParentId, Count = (int) 1, ParentId = (int) 0}
}
from item in items
select new {
Id = item.Id,
Count = item.Count,
ParentId = item.ParentId
};
Reduce = results => from result in results
group result by result.Id into g
let itemWithParent = g.FirstOrDefault(x => x.ParentId != 0)
select new
{
Id = g.Key,
Count = g.Sum(x => x.Count),
ParentId = (itemWithParent == null) ? (int)0 : itemWithParent.ParentId
};
}
}
Error returned: [WebException: The remote server returned an error: (500) Internal Server Error.] System.Net.HttpWebRequest.GetResponse() +6111651 Raven.Client.Connection.HttpJsonRequest.ReadStringInternal(Func`1 getResponse) in c:\Builds\raven\Raven.Client.Lightweight\Connection\HttpJsonRequest.cs:231
[InvalidOperationException: { "Url": "/indexes/FullTree", "Error": "System.InvalidOperationException: Could not understand query: \r\n-- line 2 col 55: invalid NewExpression\r\n-- line 2 col 91: Can't parse double .0.0\r\n-- line 2 col 183: Can't parse double .0.0\r\n-- line 2 col 275: Can't parse double .0.0\r\n\r\n at Raven.Database.Linq.QueryParsingUtils.GetVariableDeclarationForLinqMethods(String query, Boolean requiresSelectNewAnonymousType) in c:\Builds\raven-unstable\Raven.Database\Linq\QueryParsingUtils.cs:line 122\r\n at Raven.Database.Linq.DynamicViewCompiler.TransformMapDefinitionFromLinqMethodSyntax(String query, String& entityName) in c:\Builds\raven-unstable\Raven.Database\Linq\DynamicViewCompiler.cs:line 355\r\n at Raven.Database.Linq.DynamicViewCompiler.HandleMapFunction(ConstructorDeclaration ctor, String map) in c:\Builds\raven-unstable\Raven.Database\Linq\DynamicViewCompiler.cs:line 132\r\n at Raven.Database.Linq.DynamicViewCompiler.TransformQueryToClass() in c:\Builds\raven-unstable\Raven.Database\Linq\DynamicViewCompiler.cs:line 97\r\n at Raven.Database.Linq.DynamicViewCompiler.GenerateInstance() in c:\Builds\raven-unstable\Raven.Database\Linq\DynamicViewCompiler.cs:line 489\r\n at Raven.Database.DocumentDatabase.PutIndex(String name, IndexDefinition definition) in c:\Builds\raven-unstable\Raven.Database\DocumentDatabase.cs:line 717\r\n at Raven.Database.Server.Responders.Index.Put(IHttpContext context, String index) in c:\Builds\raven-unstable\Raven.Database\Server\Responders\Index.cs:line 72\r\n at Raven.Database.Server.Responders.Index.Respond(IHttpContext context) in c:\Builds\raven-unstable\Raven.Database\Server\Responders\Index.cs:line 49\r\n at Raven.Database.Server.HttpServer.DispatchRequest(IHttpContext ctx) in c:\Builds\raven-unstable\Raven.Database\Server\HttpServer.cs:line 527\r\n at Raven.Database.Server.HttpServer.HandleActualRequest(IHttpContext ctx) in c:\Builds\raven-unstable\Raven.Database\Server\HttpServer.cs:line 303" }] Raven.Client.Connection.HttpJsonRequest.ReadStringInternal(Func`1 getResponse) in c:\Builds\raven\Raven.Client.Lightweight\Connection\HttpJsonRequest.cs:295