RavenDB-筛选文档并使用索引/查询获取计数

本文关键字:查询 获取 索引 筛选 文档 RavenDB- | 更新日期: 2023-09-27 18:27:01

我有一个城市文档,站点文档。城市可以有多个站点。网站文档中包含城市信息。RavenDB 中约有100份城市文档和10000份网站文档

城市文件:

{
    "CityCode": "NY",
    "CityName": "New York"
}

现场文件:

{
    "SiteName": "MOMA",
    "CityCode": "NY"
}

目标是获得所有城市的列表和每个类似的网站的数量。。。

City   Sites
NY     12
CH      33
BO      56
and so on....

我正在这么做。

int countSites = session.Query<Site>()
                        .Count();

var SiteCityList = session.Query<Site>()
                          .Take(countSites)
                          .ToList()
                          .GroupBy(x => x.CityCode)
                          .OrderBy(x => x.Count())
                          .ToDictionary(x => x.Key, x => x.Count());

这并没有给出ravendb中的所有数据。我在任何时候都只得到11行按站点计数,甚至计数都不准确。我想要的是获得所有100个城市的列表,以及每个城市的站点数量(以100为单位),如上图所示。谢谢你的帮助。

RavenDB-筛选文档并使用索引/查询获取计数

使用类似的映射/减少索引

public class CityCodeCount : AbstractIndexCreationTask<Site, CityCodeCount.ReduceResult>
{
    public class ReduceResult
    {
        public string CityCode { get; set; }
        public int Count { get; set; }
    }
    public CityCodeCount()
    {
        Map = sites => from site in sites
                        select new
                        {
                            site.CityCode,
                            Count = 1
                        };
        Reduce = results => from result in results
                            group result by result.CityCode
                            into g
                            select new
                            {
                                CityCode = g.Key,
                                Count = g.Sum(x => x.Count)
                            };
    }
}

稍后,您可以轻松地查询它。

var results = documentSession.Query<CityCodeCount.ReduceResult, CityCodeCount>()
    .ToList();

如果你想要另一种方式,你可以看看Faceted Search

它比Map/Reduce提供了更大的灵活性,但只有当您想要一个项目计数(在您的情况下可以这样做)时,它才会起作用。

您有两个选项:

  1. 创建Map/Reduce索引并对其进行查询
  2. 使用分面(聚合)搜索进行查询

要在两者之间做出选择,请考虑

  • 专用索引的查询速度更快,但对存储和更改记录的重新索引性能有一定的影响(如果您需要立即保持一致性并等待非陈旧索引,这一点可能很重要)
  • 当您已经在现有索引中包含字段时,Facet使用起来更简单。我相信您了解静态索引的重要性,并且已经有了一些

虽然使用Map/Reduce索引很简单,Daniel的回答已经涵盖了这一点,但我在下面提供了一个使用Facets:的例子

var query = DbSession.Query<Site_IndexModel, Site_ForList>();
List<FacetValue> facetResults = (await query
                                        .AggregateBy(builder => builder.ByField(s => s.CityCode ))
                                        .ExecuteAsync()
                                ).Single().Value.Values;
// Go through results, where each facetResult is { Range, Count } structure
return  from result in facetResults
        select new { CityCode = result.Range, Count = result.Count }

其中

  • Site_ForListSite集合的现有索引,其中包括CityCode字段
  • Site_IndexModelSite_ForList索引的存储结构