2

如何AbstractIndexCreationTask为以下场景创建合适的?

对于多个博客的场景,如何从特定博客中获取标签以及这些博客的标签计数

对存储在 RavenDB 中的数据结构感兴趣的成员:

public class BlogPost {
    public string BlogKey { get; set; }
    public IEnumerable<string> Tags { get; set; }
    /* ... */
}

我需要实现的方法具有以下签名:

public Dictionary<string, int> GetTagsByBlogs(string tag, params string[] blogKeys)

在普通的 LINQ 中,我会这样写:

var tags = from post in blogPosts
           from tag in post.Tags
           where blogKeys.Contains(post.BlogKey)
           group tag by tag into g
           select new {
               Tag = g.Key,
               Count = g.Count(),
           };

但 RavenDB 既不支持SelectMany也不GroupBy支持。我已经为 map-reduce 解决方案尝试了不同的组合,但我无法弄清楚如何做到这一点,因为map 和 reduce 在 data-structure 方面不同

4

2 回答 2

3

在RavenDB的知识库中描述了如何创建标签云。

在您的情况下,您必须BlogKey在索引中包含,尤其是在group by子句中:

public class Tags_Count : AbstractIndexCreationTask<BlogPost, Tags_Count.ReduceResult>
{
    public class ReduceResult
    {
        public string BlogKey { get; set; }
        public string Name { get; set; }
        public int Count { get; set; }
    }

    public Tags_Count()
    {
        Map = posts => from post in posts
                       from tag in post.Tags
                       select new { 
                           BlogKey = post.BlogKey,
                           Name = tag.ToString().ToLower(), 
                           Count = 1 
                       };
        Reduce = results => from tagCount in results
                            group tagCount by new { 
                                tagCount.BlogKey,  
                                tagCount.Name } into g
                            select new {
                                BlogKey = g.Key.BlogKey,
                                Name = g.Key.Name, 
                                Count = g.Sum(x => x.Count) 
                            };

        Sort(result => result.Count, SortOptions.Int); 
    }
}

然后使用所需的 BlogKey 查询该索引:

var result = session.Query<Tags_Count.ReduceResult, Tags_Count>()
    .Where(x => x.BlogKey = myBlogKey)
    .OrderByDescending(x => x.Count)
    .ToArray();

如果需要查询多个博客,可以试试这个查询:

var tagsByBlogs = session.Query<Tags_Count.ReduceResult, Tags_Count>()
    .Where(x => x.BlogKey.In<string>(blogKeys))
    .OrderByDescending(x => x.Count)
    .ToArray();

AFAIK 是您可以通过索引获得的。您仍然必须像在原始问题中那样在客户端聚合结果,除了您可以跳过 blogKeys 上的过滤:

var tags = from tag in tagsByBlogs
           group tag by Name into g
           select new {
               Tag = g.Key,
               Count = g.Count(),
           };
于 2012-04-19T13:54:22.057 回答
1

看看faceted search,你可以在查询时指定条件,像这样:

var facetResults = s.Query<BlogPost>("BlogIndex") 
                        .Where(x => x.BlogKey == "1" || x.BlogKey == "5" ...) 
                        .ToFacets("facets/BlogFacets");

然后对匹配 where 子句的所有结果进行分组(和计数)。

更新您需要一个看起来像这样的索引:

from post in blogPosts
from tag in post.Tags 
select new 
{
    post.BlogKey
    Tag = tag     
}
于 2012-04-19T16:27:03.973 回答