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いません。GroupBymap-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 に答える