使用 Multi Map/Reduce 合并相关实体

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前, 星球 内第2个项目《仿小红书(微服务架构)》正在更新中。第1个项目:全栈前后端分离博客项目已经完结,演示地址:http://116.62.199.48/。采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 255 小节,累计 39w+ 字,讲解图:1716 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 1300+ 小伙伴加入,欢迎点击围观

邮件列表中出现了一个关于跨相关实体搜索的问题。特别是,场景是 MMPROG 游戏中玩家和角色的概念。

播放器文档如下所示:

 {
  "Id": "players/bella@dona.self",
  “名称”:“贝拉多娜”,
  “计费”:[{...},{...}],
  “成人”:假的,
  “上次登录”:“2015-03-11”
}

而一个玩家有多个角色文件:

 {
  "Id": "字符数/1234",
  “名称”:“黑多纳”,
  “玩家”:“玩家/bella@dona.self”,
  “种族”:“黑暗精灵”,
  “等级”:24,
  “经验值”:283831,
  “生命值”:438,
  “技能”:[ { ... } , { ... } ]
}
 {
  "Id": "字符数/1321",
  “名称”:“蓝铃”,
  “玩家”:“玩家/bella@dona.self”,
  “种族”:“半身人”,
  “级别”:2,
  “经验值”:2831,
  “惠普”:18,
  “技能”:[ { ... } , { ... } ]
}
 {
  "Id": "字符数/1143",
  “名称”:“棕色理发师”,
  “玩家”:“玩家/bella@dona.self”,
  “种族”:“木精灵”,
  “等级”:44,
  “经验值”:983831,
  “生命值”:718,
  “技能”:[ { ... } , { ... } ]
}

我们想要的是这样的输出:

 {
    “ID”:“玩家/bella@dona.self”,
    “成人”:假的,
    “人物” : [
        { "Id": "characters/1234", "Name": "Black Dona" },
        { "Id": "characters/1321", "Name": "Blue Bell" },
        { "Id": "characters/1143", "Name": "Brown Barberl" },
    ]
}

现在,一个真正简单的方法是发出两个查询。一个找到玩家,另一个找到角色。这实际上是执行此操作的首选方法。但是假设我们需要做一些同时使用两种文档类型的事情。

例如,给我所有角色超过 40 岁的非成年人玩家。为此,我们将使用多映射缩减索引将两者合并在一起。这是它的样子:

 // 地图 - 玩家

来自 docs.Players 中的播放器 选择新的 { Player = player.Id, 成人 = player.Adult, 字符 = 新对象[0] }

// 地图 - 字符

来自 docs.Characters 中的字符 选择新的 { character.Player, 成人 = 假, 字符=新[] { 新的 { 字符.Id, 字符.Name } } }

// 减少

从结果到结果 按 result.Player 将结果分组为 g 选择新的 { 玩家 = g.Key, 成人 = g.Any(x=>x.Adult), 字符 = g.SelectMany(x=>x.Characters) }

这会在一个地方为您提供所有详细信息。您可以从那里开始处理查询。