我正面临一个索引问题,但我还没有找到解决方案。
我每个主板都有以下文档结构:
{
"Name": "Test Board",
...
"Settings": {
"Admins": [ "USER1", "USER2" ],
"Members": [ "USER3", "USER4", "USER5" ]
...
},
...
"CreatedBy": "USER1",
"CreatedOn": "2014-09-26T18:14:20.0858945"
...
}
现在我希望能够检索在董事会中注册的所有用户的数量。当然,这不仅应计算用户出现次数,还要计算不同用户的数量。一个用户可以是多个板的成员。
此操作应尽可能快地执行,因为它显示在每页上可见的全局统计信息板中。因此,我选择使用索引进行尝试,而不是检索所有主板及其用户,并在客户端进行工作。
尝试使用Map / Reduce索引实现此目的:
Map = boards => from board in boards
select new
{
Aggregation = "ALL",
Users = new object[]
{
board.CreatedBy,
board.Settings.Admins,
board.Settings.Members
},
NumberOfUsers = 1
};
Reduce = results => from res in results
group res by new
{
res.Aggregation
}
into g
select new
{
g.Key.Aggregation,
Users = g.Select(x => x.Users),
NumberOfUsers = g.Sum(x => x.Users.Length)
};
显然这会导致计数错误。我对Reduce没有任何经验,所以我很感激任何提示!解决方案可能很简单......
全局区分CreatedBy,管理员和所有文档的成员以及返回计数的最佳方式是什么?
提前致谢!
答案 0 :(得分:0)
使用这样的索引:
from board in docs.Boards
select new
{
Users = board.Settings.Admins.Count + board.Settings.Members.Count + 1 /* created by */
}
from r in results
group r by "all" into g
select new
{
Users = g.Sum(x=>x.Users)
}
答案 1 :(得分:0)
到目前为止我能说的最好的是:
Map = boards => from board in boards
select new
{
Users = new object[]
{
board.CreatedBy,
board.Settings.Admins,
board.Settings.Members
}
};
Reduce = results => from r in results
group r by "all" into g
select new
{
Users = g.SelectMany(x => x.Users)
};
然后查询不同的用户数:
var allUsersQuery = _documentSession.Query<AllUsersIndex.Result, AllUsersIndex>();
return allUsersQuery.Any() ? allUsersQuery.First().Users.Distinct().Count() : 0;
至少查询只返回所有板上所有用户名的列表,而不是更大的对象树。但是,必须在客户端完成唯一性。
如果有更好的方法请告诉我。只从服务器返回一个整数就很漂亮了......
答案 2 :(得分:0)
然后使用:
from board in docs.Boards
from user in board.Settings.Admins.Concat(board.Settings.Members).Concat(new[]{board.CreatedBy})
select new
{
User = user,
Count = 1
}
from r in results
group r by r.User into g
select new
{
User = g.Key,
Count = g.Sum(x=>x.Count)
}
我对扇出不是很满意,但这会给你所有的discint用户和他们出现的次数。 如果您只想要不同用户的数量,只需从索引中获取总结果。