see on GitHub

Indexes: Indexing Counters



Syntax

In order to index counter values, create an index that inherits from AbstractCountersIndexCreationTask. Next, choose one of these two methods which take the index expression:

protected void AddMapForAll(Expression<Func<IEnumerable<CounterEntry>, IEnumerable>> map)

protected void AddMap(string counter, Expression<Func<IEnumerable<CounterEntry>, IEnumerable>> map)

AddMapForAll indexes all the counters in the indexed documents. AddMap only indexes the counters with the specified name.

Examples of indexes using each method:

private class MyCounterIndex : AbstractCountersIndexCreationTask<Company>
{
    public MyCounterIndex()
    {
        AddMap("Likes", counters => from counter in counters
                                        select new
                                        {
                                            Likes = counter.Value,
                                            Name = counter.Name,
                                            User = counter.DocumentId
                                        });
    }
}
private class MyCounterIndex_AllCounters : AbstractCountersIndexCreationTask<Company>
{
    public MyCounterIndex_AllCounters()
    {
        AddMapForAll(counters => from counter in counters
                                 select new
                                 {
                                     Count = counter.Value,
                                     Name = counter.Name,
                                     User = counter.DocumentId
                                 });
    }
}



AbstractJavaScriptCountersIndexCreationTask

Creating an index inheriting from AbstractJavaScriptCountersIndexCreationTask allows you to write your map and reduce functions in JavaScript.
Learn more about JavaScript indexes here.

public class AbstractJavaScriptCountersIndexCreationTask : AbstractCountersIndexCreationTask
{
    public HashSet<string> Maps;
    protected string Reduce;
}
Property Type Description
Maps HashSet<string> The set of javascript map functions
Reduce string The javascript reduce function

Example:

private class MyMultiMapCounterIndex : AbstractJavaScriptCountersIndexCreationTask
{
    public MyMultiMapCounterIndex()
    {
        Maps = new HashSet<string>
        {
            @"counters.map('Blogposts', 'Likes', function (counter) {
                return {
                    Likes: counter.Value,
                    Name: counter.Name,
                    Blog Post: counter.DocumentId
                };
            })"
        };
    }
}

CounterNamesFor

While indexes inheriting from AbstractIndexCreationTask cannot index counter values, the CounterNamesFor method is available which returns the names of all counters for a specified document:

IEnumerable<string> CounterNamesFor(object doc);

Example of index using CounterNamesFor:

public class Companies_ByCounterNames : AbstractIndexCreationTask<Company>
{
    public class Result
    {
        public string[] CounterNames { get; set; }
    }

    public Companies_ByCounterNames()
    {
        Map = employees => from e in employees
                           let counterNames = CounterNamesFor(e)
                           select new Result
                           {
                               CounterNames = counterNames.ToArray()
                           };
    }
}

Querying the Index

// return all companies that have 'Likes' counter
List<Company> companies = session
    .Query<Companies_ByCounterNames.Result, Companies_ByCounterNames>()
    .Where(x => x.CounterNames.Contains("Likes"))
    .OfType<Company>()
    .ToList();
// return all companies that have 'Likes' counter
List<Company> companies = await asyncSession
    .Query<Companies_ByCounterNames.Result, Companies_ByCounterNames>()
    .Where(x => x.CounterNames.Contains("Likes"))
    .OfType<Company>()
    .ToListAsync();
// return all companies that have 'Likes' counter
List<Company> companies = session
    .Advanced
    .DocumentQuery<Company, Companies_ByCounterNames>()
    .ContainsAny("CounterNames", new[] { "Likes" })
    .ToList();