MultiMap / Reduce - Counts = 0? - mapreduce

I want to create an index for a query, I want to return to my view a list of Audio items along with statistics for these items, which are TotalDownloads & TotalPlays.
Here are my relevant docs:
Audio
- Id
- ArtistName
- Name
AudioCounter
- AudioId
- Type
- DateTime
Here is my current Index:
public class AudioWithCounters : AbstractMultiMapIndexCreationTask<AudioWithCounters.AudioViewModel>
{
public class AudioViewModel
{
public string Id { get; set; }
public string ArtistName { get; set; }
public string Name { get; set; }
public int TotalDownloads { get; set; }
public int TotalPlays { get; set; }
}
public AudioWithCounters()
{
AddMap<Audio>(audios => from audio in audios
select new
{
Id = audio.Id,
ArtistName = audio.ArtistName,
Name = audio.Name,
TotalDownloads = 0,
TotalPlays = 0
});
AddMap<AudioCounter>(counters => from counter in counters
where counter.Type == Core.Enums.Audio.AudioCounterType.Download
select new
{
Id = counter.AudioId,
ArtistName = (string)null,
Name = (string)null,
TotalDownloads = 1,
TotalPlays = 0
});
AddMap<AudioCounter>(counters => from counter in counters
where counter.Type == Core.Enums.Audio.AudioCounterType.Download
select new
{
Id = counter.AudioId,
ArtistName = (string)null,
Name = (string)null,
TotalDownloads = 0,
TotalPlays = 1
});
Reduce = results => from result in results
group result by result.Id
into g
select new
{
Id = g.Key,
ArtistName = g.Select(x => x.ArtistName).Where(x => x != null).First(),
Name = g.Select(x => x.Name).Where(x => x != null).First(),
TotalDownloads = g.Sum(x => x.TotalDownloads),
TotalPlays = g.Sum(x => x.TotalPlays)
};
}
}
However, my TotalDownloads & TotalPlays are always 0 even though there should be data in there. What am I doing wrong?

In the reduce function, replace .First() with .FirstOrDefault(), then it works.
Besides that, there is a typo in the second map-function, because you are filtering on the same AudioCounterType.Download.

Related

How to get meta tags value from search engine optimization in SharePoint 2013

¿How to read meta tags in SharePoint 2013 in every page with friendly url?
Thanks in advance.
Ok,
I found the answer debuggin, this work for me.
public class SEOProperties {
public string PropBrowserTitle { get; set; }
public string PropBrowserDescription { get; set; }
public string PropBrowserKeyWords { get; set; }
public string PropBrowserSiteNoIndex { get; set; }
}
private SEOProperties GetSEOProperties(){
SEOProperties SEO = new SEOProperties();
if (SPContext.Current != null)
{
Guid siteGuid = SPContext.Current.Site.ID;
Guid webGuid = SPContext.Current.Web.ID;
using (SPSite site = new SPSite(siteGuid))
{
using (SPWeb web = site.OpenWeb())
{
TaxonomySession session = new TaxonomySession(site);
NavigationTerm navTermino = TaxonomyNavigationContext.Current.NavigationTerm;
Term termino = navTermino.GetTaxonomyTerm(session);
var SEOPropBrowserTitle = termino.LocalCustomProperties.Where(o => o.Key == "_Sys_Seo_PropBrowserTitle").SingleOrDefault();
var SEOPropDescription = termino.LocalCustomProperties.Where(o => o.Key == "_Sys_Seo_PropDescription").SingleOrDefault();
var SEOPropKeyWords = termino.LocalCustomProperties.Where(o => o.Key == "_Sys_Seo_PropKeywords").SingleOrDefault();
var SEOPropSiteNoIndex = termino.LocalCustomProperties.Where(o => o.Key == "_Sys_Seo_PropSitemapNoIndex").SingleOrDefault();
SEO.PropBrowserDescription = SEOPropDescription.Value;
SEO.PropBrowserKeyWords = SEOPropKeyWords.Value;
SEO.PropBrowserSiteNoIndex = SEOPropSiteNoIndex.Value;
SEO.PropBrowserTitle = SEOPropBrowserTitle.Value;
}
}
}
return SEO;
}

RavenDB: Why do I get null-values for fields in this multi-map/reduce index?

Inspired by Ayende's article https://ayende.com/blog/89089/ravendb-multi-maps-reduce-indexes, I have the following index, that works as such:
public class Posts_WithViewCountByUser : AbstractMultiMapIndexCreationTask<Posts_WithViewCountByUser.Result>
{
public Posts_WithViewCountByUser()
{
AddMap<Post>(posts => from p in posts
select new
{
ViewedByUserId = (string) null,
ViewCount = 0,
Id = p.Id,
PostTitle = p.PostTitle,
});
AddMap<PostView>(postViews => from postView in postViews
select new
{
ViewedByUserId = postView.ViewedByUserId,
ViewCount = 1,
Id = (string) postView.PostId,
PostTitle = (string) null,
});
Reduce = results => from result in results
group result by new
{
result.Id,
result.ViewedByUserId
}
into g
select new Result
{
ViewCount = g.Sum(x => x.ViewCount),
Id = g.Key.Id,
ViewedByUserId = g.Key.ViewedByUserId,
PostTitle = g.Select(x => x.PostTitle).Where(x => x != null).FirstOrDefault(),
};
Store(x => x.PostTitle, FieldStorage.Yes);
}
public class Result
{
public string Id { get; set; }
public string ViewedByUserId { get; set; }
public int ViewCount { get; set; }
public string PostTitle { get; set; }
}
}
I want to query this index like this:
Return all posts including - for a given user - the integer of how many times, the user has viewed the post. The "views" are stored in a separate document type, PostView. Note, that my real document types have been renamed here to match the example from the article (I certainly would not implement "most-viewed" this way).
The result from the query I get is correct - i.e. I always get all the Post documents with the correct view-count for the user. But my problem is, the PostTitle field always is null in the result set (all Post documents have a non-null value in the dataset).
I'm grouping by the combination of userId and (post)Id as my "uniqueness". The way I understand it (and please correct me if I'm wrong), is, that at this point in the reduce, I have a bunch of pseudo-documents with identical userId /postId combination, some of which come from the Post map, others from the PostView map. Now I simply find any single pseudo-document of the ones, that actually have a value for PostTitle - i.e. one that originates from the Post map. These should all obviously have the same value, as it's the same post, just "outer-joined". The .Select(....).Where(....).FirstOrDefault() chain is taken from the very example I used as a base. I then set this ViewCount value for my final document, which I project into the Result.
My question is: how do I get the non-null value for the PostTitle field in the results?
The problem is that you have:
ViewedByUserId = (string) null,
And:
group result by new
{
result.Id,
result.ViewedByUserId
}
into g
In other words, you are actually grouping by null, which I'm assuming that isn't your intent.
It would be much simpler to have a map/reduce index just on PostView and get the PostTitle from an include or via a transformer.
You understanding of what is going on is correct, in the sense that you are creating index results with userId / postId on them.
Buit what you are actually doing is creating results from PostView with userId /postId and from Post with null /postId.
And that is why you don't have the matches that you want.
The grouping in the index is incorrect. With the following sample data:
new Post { Id = "Post-1", PostTitle = "Post Title", AuthorId = "Author-1" }
new PostView { ViewedByUserId = "User-1", PostId = "Post-1" }
new PostView { ViewedByUserId = "User-1", PostId = "Post-1" }
new PostView { ViewedByUserId = "User-2", PostId = "Post-1" }
The index results are like this:
ViewCount | Id | ViewedByUserId | PostTitle
--------- | ------ | -------------- | ----------
0 | Post-1 | null | Post Title
2 | Post-1 | User-1 | null
1 | Post-1 | User-2 | null
The map operation in the index simply creates a common document for all source documents. Thus, the Post-1 document produces one row, the two documents for Post-1 and User-1 produce two rows (which are later reduced to the single row with ViewCount == 2) and the document for Post-1 and User-2 produces the last row.
The reduce operation the groups all the mapped rows and produces the resulting documents in the index. In this case, the Post-sourced document is stored separately from the PostView-sourced documents because the null value in the ViewedByUserId is not grouped with any document from the PostView collection.
If you can change your way of storing data, you can solve this issue by storing the number of views directly in the PostView. It would greatly reduce duplicate data in your database while having almost the same cost when updating the view count.
Complete test (needs xunit and RavenDB.Tests.Helpers nugets):
using Raven.Abstractions.Indexing;
using Raven.Client;
using Raven.Client.Indexes;
using Raven.Tests.Helpers;
using System.Linq;
using Xunit;
namespace SO41559770Answer
{
public class SO41559770 : RavenTestBase
{
[Fact]
public void SO41559770Test()
{
using (var server = GetNewServer())
using (var store = NewRemoteDocumentStore(ravenDbServer: server))
{
new PostViewsIndex().Execute(store);
using (IDocumentSession session = store.OpenSession())
{
session.Store(new Post { Id = "Post-1", PostTitle = "Post Title", AuthorId = "Author-1" });
session.Store(new PostView { Id = "Views-1-1", ViewedByUserId = "User-1", PostId = "Post-1", ViewCount = 2 });
session.Store(new PostView { Id = "Views-1-2", ViewedByUserId = "User-2", PostId = "Post-1", ViewCount = 1 });
session.SaveChanges();
}
WaitForAllRequestsToComplete(server);
WaitForIndexing(store);
using (IDocumentSession session = store.OpenSession())
{
var resultsForId1 = session
.Query<PostViewsIndex.Result, PostViewsIndex>()
.ProjectFromIndexFieldsInto<PostViewsIndex.Result>()
.Where(x => x.PostId == "Post-1" && x.UserId == "User-1");
Assert.Equal(2, resultsForId1.First().ViewCount);
Assert.Equal("Post Title", resultsForId1.First().PostTitle);
var resultsForId2 = session
.Query<PostViewsIndex.Result, PostViewsIndex>()
.ProjectFromIndexFieldsInto<PostViewsIndex.Result>()
.Where(x => x.PostId == "Post-1" && x.UserId == "User-2");
Assert.Equal(1, resultsForId2.First().ViewCount);
Assert.Equal("Post Title", resultsForId2.First().PostTitle);
}
}
}
}
public class PostViewsIndex : AbstractIndexCreationTask<PostView, PostViewsIndex.Result>
{
public PostViewsIndex()
{
Map = postViews => from postView in postViews
let post = LoadDocument<Post>(postView.PostId)
select new
{
Id = postView.Id,
PostId = post.Id,
PostTitle = post.PostTitle,
UserId = postView.ViewedByUserId,
ViewCount = postView.ViewCount,
};
StoreAllFields(FieldStorage.Yes);
}
public class Result
{
public string Id { get; set; }
public string PostId { get; set; }
public string PostTitle { get; set; }
public string UserId { get; set; }
public int ViewCount { get; set; }
}
}
public class Post
{
public string Id { get; set; }
public string PostTitle { get; set; }
public string AuthorId { get; set; }
}
public class PostView
{
public string Id { get; set; }
public string ViewedByUserId { get; set; }
public string PostId { get; set; }
public int ViewCount { get; set; }
}
}

Traverse n-level parent child list C#

I have a parent-child list. It can be of n-level.
I need each item within this hierarchy.
I am using 'foreach' loop and recursive function but it's not working.
I have went through other solutions at 'stackoverflow' but none of them worked for me.
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
private List<Item> children = new List<Item>();
public List<Item> Children
{
get { return children; }
set { children = value; }
}
}
List<Item> test = new List<Item>();
test.Add(new Item { Id = 1, Name = "Root1", ParentId = -1 });
test[0].Children.Add(new Item { Id = 4, Name = "child-1-Root1", ParentId = 1 });
test[0].Children[0].Children.Add(new Item { Id = 10, Name = "grandchild-1-Root1", ParentId = 4 });
test[0].Children.Add(new Item { Id = 5, Name = "child-2-Root1", ParentId = 1 });
test.Add(new Item { Id = 2, Name = "Root2", ParentId = -1 });
test[1].Children.Add(new Item { Id = 6, Name = "child-1-Root2", ParentId = 2 });
test[1].Children.Add(new Item { Id = 7, Name = "child-2-Root2", ParentId = 2 });
test.Add(new Item { Id = 3, Name = "Root3", ParentId = -1 });
test[2].Children.Add(new Item { Id = 8, Name = "child-1-Root3", ParentId = 3 });
test[2].Children.Add(new Item { Id = 9, Name = "child-2-Root3", ParentId = 3 });
The solution is:
public static Find()
{
foreach (var item in test)
{
FindRecursively(item, item.Name);
}
}
public static Item FindRecursively(Item node, string name)
{
if (node == null)
return null;
if (node.Name == name)
Console.WriteLine(node.Name);
foreach (var child in node.Children)
{
var found = FindRecursively(child, child.Name);
}
return null;
}

Failure in Multi Map Index with Spatial Index in RavenDB

I want to search for things that belong to users (near me). I have the following index defined, but I am not getting a merged resultset:
public class Things_ByLocation : AbstractMultiMapIndexCreationTask<Things_ByLocation.ThingsByLocationResult>
{
public class ThingsByLocationResult
{
public string ThingId { get; set; }
public string UserId { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public Things_ByLocation()
{
AddMap<Thing>(things => from t in things
select new
{
ThingId = t.Id,
UserId = (string)null,
Latitude = 0,
Longitude = 0,
_ = (object)null,
});
AddMap<User>(users => from u in users
select new
{
ThingId = (string)null,
UserId = u.Id,
Latitude = u.Latitude,
Longitude = u.Longitude,
_ = SpatialIndex.Generate(u.Latitude, u.Longitude)
});
Reduce = results => from result in results
group result by result.ThingId into g
let userId = g.Select(x => x.UserId).Where(t => !string.IsNullOrWhiteSpace(t)).FirstOrDefault()
let lat = g.Select(x => x.Latitude).Where(t => t != 0).FirstOrDefault()
let lng = g.Select(x => x.Longitude).Where(t => t != 0).FirstOrDefault()
select new
{
ThingId = g.Key,
UserId = userId,
Latitude = lat,
Longitude = lng,
_ = SpatialIndex.Generate(lat, lng)
};
Store(x => x.ThingId, FieldStorage.Yes);
Store(x => x.UserId, FieldStorage.Yes);
}
}
Result looks like this:
{
"ThingId": "Thing/Id26",
"UserId": null,
"Longitude": "0",
"__spatialShape": "0.000000 0.000000"
}
My models:
public class User
{
public string Id { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public class Thing
{
public string Id { get; set; }
public double Name { get; set; }
public double Description { get; set; }
public string UserId { get; set; }
}
Any ideas as to what I am doing wrong? If I switch the group to the user, the user section gets populated and the ThingId is null. Hence, it appears that the merging process is failing. I'm just not sure why.
It is also very odd, as to why the result show the Longitude, but not the Latitude property.
Working with RavenDB Build 960 in RAM.
I realise I could denormalize the location into the Thing, but that would mean that if the user location changed I would have to update potentially hundreds of Things. Is that the preferred NoSql way to do this?
UPDATE
Based on Ayende's suggestion I now have the following:
public class Things_ByLocation : AbstractMultiMapIndexCreationTask<Things_ByLocation.ThingsByLocationResult>
{
public class ThingsByLocationResult
{
public string ThingId { get; set; }
public string UserId { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public Things_ByLocation()
{
AddMap<Thing>(things => from t in things
select new
{
ThingId = t.Id,
UserId = (string)null,
Latitude = 0,
Longitude = 0
});
AddMap<User>(users => from u in users
select new
{
ThingId = (string)null,
UserId = u.Id,
Latitude = u.Latitude,
Longitude = u.Longitude
});
Reduce = results => from result in results
group result by result.ThingId into g
select new
{
ThingId = g.Key,
UserId = g.Select(x => x.UserId).Where(x => x != null).FirstOrDefault(),
Latitude = g.Select(x => x.Latitude).Where(t => t != 0).FirstOrDefault(),
Longitude = g.Select(x => x.Longitude).Where(t => t != 0).FirstOrDefault()
};
Store(x => x.ThingId, FieldStorage.Yes);
Store(x => x.UserId, FieldStorage.Yes);
}
}
The index itself:
Map:
docs.Things
.Select(t => new {ThingId = t.__document_id, UserId = (String)null, Latitude = 0, Longitude = 0})
Map:
docs.Users
.Select(u => new {ThingId = (String)null, UserId = u.__document_id, Latitude = ((double)u.Latitude), Longitude = ((double)u.Longitude)})
Reduce:
results
.GroupBy(result => result.ThingId)
.Select(g => new {ThingId = g.Key, UserId = g
.Select(x => x.UserId)
.Where(x => x != null).FirstOrDefault(), Latitude = g
.Select(x => ((double)x.Latitude))
.Where(t => t != 0).FirstOrDefault(), Longitude = g
.Select(x => ((double)x.Longitude))
.Where(t => t != 0).FirstOrDefault()})
The resulting projection looks like this:
{
"ThingId": "Thing/Id26",
"UserId": null,
"Latitude": null,
"Longitude": null
}
I appear to be doing something academically wrong here.
Try:
Removing SpatialIndex.Generate from the map, it should only be on the reduce.
Removing SpatialIndex.Generate from the reduce and just seeing why you don't the Latitude & Longitude as you should.
Through a process of trial and error (and Ayende's suggestion), I ended up with the following. It works works, but I have no idea why!
I have a suspicion that I would be best changing the data model and denormalize the geo location data into the Thing.
public class Things_ByLocation : AbstractMultiMapIndexCreationTask<Things_ByLocation.ThingsByLocationResult>
{
public class ThingsByLocationResult
{
public string Id { get; set; }
public string UserId { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public string SKU { get; set; }
public string Name { get; set; }
}
public Things_ByLocation()
{
AddMap<Thing>(things => from t in things
select new
{
Id = t.Id,
UserId = t.UserId,
Latitude = 0,
Longitude = 0,
Name = t.Name,
SKU = t.SKU,
_ = (object)null,
});
AddMap<User>(users => from u in users
select new
{
Id = (string)null,
UserId = u.Id,
Latitude = u.Latitude,
Longitude = u.Longitude,
Name = (string)null,
SKU = (string)null,
_ = (object)null,
});
Reduce = results => from result in results
group result by result.Id into g
let lat = g.Select(x => x.Latitude).Where(x => x != 0).FirstOrDefault()
let lng = g.Select(x => x.Longitude).Where(x => x != 0).FirstOrDefault()
let userId = g.Select(x => x.UserId).Where(x => x != null).FirstOrDefault()
let name = g.Select(x => x.Name).Where(x => x != null).FirstOrDefault()
let sku = g.Select(x => x.SKU).Where(x => x != null).FirstOrDefault()
select new
{
Id = g.Key,
UserId = userId,
Latitude = lat,
Longitude = lng,
Name = name,
SKU = sku,
_ = SpatialIndex.Generate(lat, lng)
};
Store(x => x.Id, FieldStorage.Yes);
Store(x => x.UserId, FieldStorage.Yes);
TransformResults = (database, results) => from result in results
let user = database.Load<User>(result.UserId)
select new
{
Id = result.Id,
UserId = result.UserId,
Latitude = user.Latitude,
Longitude = user.Longitude,
Name = result.Name,
SKU = result.SKU,
};
}
}

RavenDB MultiMapReduce Sum not returning the correct value

Sorry for this lengthy query, I decided to add the whole test so that it will be easier for even newbies to help me with this total brain-melt.
The using directives are:
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Raven.Client;
using Raven.Client.Embedded;
using Raven.Client.Indexes;
Please leave feedback if I'm too lengthy, but what could possibly go wrong if I add a complete test?
[TestFixture]
public class ClicksByScoreAndCardTest
{
private IDocumentStore _documentStore;
[SetUp]
public void SetUp()
{
_documentStore = new EmbeddableDocumentStore {RunInMemory = true}.Initialize();
_documentStore.DatabaseCommands.DisableAllCaching();
IndexCreation.CreateIndexes(typeof (ClicksBySearchAndProductCode).Assembly, _documentStore);
}
[TearDown]
public void TearDown()
{
_documentStore.Dispose();
}
[Test]
public void ShouldCountTotalLeadsMatchingPreference()
{
var userFirst = new User {Id = "users/134"};
var userSecond = new User {Id = "users/135"};
var searchFirst = new Search(userFirst)
{
Id = "searches/24",
VisitId = "visits/63"
};
searchFirst.Result = new Result();
searchFirst.Result.Rows = new List<Row>(
new[]
{
new Row {ProductCode = "CreditCards/123", Score = 6},
new Row {ProductCode = "CreditCards/124", Score = 4}
});
var searchSecond = new Search(userSecond)
{
Id = "searches/25",
VisitId = "visits/64"
};
searchSecond.Result = new Result();
searchSecond.Result.Rows = new List<Row>(
new[]
{
new Row {ProductCode = "CreditCards/122", Score = 9},
new Row {ProductCode = "CreditCards/124", Score = 4}
});
var searches = new List<Search>
{
searchFirst,
searchSecond
};
var click = new Click
{
VisitId = "visits/64",
ProductCode = "CreditCards/122",
SearchId = "searches/25"
};
using (var session = _documentStore.OpenSession())
{
foreach (var search in searches)
{
session.Store(search);
}
session.Store(click);
session.SaveChanges();
}
IList<ClicksBySearchAndProductCode.MapReduceResult> clicksBySearchAndProductCode = null;
using (var session = _documentStore.OpenSession())
{
clicksBySearchAndProductCode = session.Query<ClicksBySearchAndProductCode.MapReduceResult>(ClicksBySearchAndProductCode.INDEX_NAME)
.Customize(x => x.WaitForNonStaleResults()).ToArray();
}
Assert.That(clicksBySearchAndProductCode.Count, Is.EqualTo(4));
var mapReduce = clicksBySearchAndProductCode
.First(x => x.SearchId.Equals("searches/25")
&& x.ProductCode.Equals("CreditCards/122"));
Assert.That(mapReduce.Clicks,
Is.EqualTo(1));
}
}
public class ClicksBySearchAndProductCode :
AbstractMultiMapIndexCreationTask
<ClicksBySearchAndProductCode.MapReduceResult>
{
public const string INDEX_NAME = "ClicksBySearchAndProductCode";
public override string IndexName
{
get { return INDEX_NAME; }
}
public class MapReduceResult
{
public string SearchId { get; set; }
public string ProductCode { get; set; }
public string Score { get; set; }
public int Clicks { get; set; }
}
public ClicksBySearchAndProductCode()
{
AddMap<Search>(
searches =>
from search in searches
from row in search.Result.Rows
select new
{
SearchId = search.Id,
ProductCode = row.ProductCode,
Score = row.Score.ToString(),
Clicks = 0
});
AddMap<Click>(
clicks =>
from click in clicks
select new
{
SearchId = click.SearchId,
ProductCode = click.ProductCode,
Score = (string)null,
Clicks = 1
});
Reduce =
results =>
from result in results
group result by
new { SearchId = result.SearchId, ProductCode = result.ProductCode }
into g
select
new
{
SearchId = g.Key.SearchId,
ProductCode = g.Key.ProductCode,
Score = g.First(x => x.Score != null).Score,
Clicks = g.Sum(x => x.Clicks)
};
}
}
public class User
{
public string Id { get; set; }
}
public class Search
{
public string Id { get; set; }
public string VisitId { get; set; }
public User User { get; set; }
private Result _result = new Result();
public Result Result
{
get { return _result; }
set { _result = value; }
}
public Search(User user)
{
User = user;
}
}
public class Result
{
private IList<Row> _rows = new List<Row>();
public IList<Row> Rows
{
get { return _rows; }
set { _rows = value; }
}
}
public class Row
{
public string ProductCode { get; set; }
public int Score { get; set; }
}
public class Click
{
public string VisitId { get; set; }
public string SearchId { get; set; }
public string ProductCode { get; set; }
}
My problem here is that I expect Count to be one in that specific test, but it just doesn't seem to add the Clicks in the Click map and the result is 0 clicks. I'm totally confused, and I'm sure that there is a really simple solution to my problem, but I just can't find it..
..hope there is a week-end warrior out there who can take me under his wings.
Yes, it was a brain-melt, for me non-trivial, but still. The proper reduce should look like this:
Reduce =
results =>
from result in results
group result by
new { SearchId = result.SearchId, ProductCode = result.ProductCode }
into g
select
new
{
SearchId = g.Key.SearchId,
ProductCode = g.Key.ProductCode,
Score = g.Select(x=>x.Score).FirstOrDefault(),
Clicks = g.Sum(x => x.Clicks)
};
Not all Maps had the Score set to a non-null-value, and therefore my original version had a problem with:
Score = g.First(x => x.Score != null).Score
Mental note, use:
Score = g.Select(x=>x.Score).FirstOrDefault()
Don't use:
Score = g.First(x => x.Score != null).Score