Couchbase Lite Join查询返回文档数量远超预期问题求解
问题原因
你返回结果数量远超预期的核心问题是Join关联条件缺失,具体如下:
- 当前child表的Join仅关联了和parent表的
parentId字段,没有将player表中存储的childId与child表对应的唯一标识字段做关联,导致每条player记录会匹配到所有归属同一parent的child记录,产生了笛卡尔积,最终结果数成倍膨胀。 - 按照你给出的示例数据计算,符合条件的player有2条,每条匹配1条parent记录,每条parent匹配2条child记录,最终就会得到212=4条结果,你实际得到12条是因为数据库中存储的parent、child记录数比你给出的示例更多。
修复方案
调整child表的Join关联规则,新增player表childId和child表childId的匹配条件即可,修改后的代码如下:
public void chosenFamily(int playerId){ String aliasPlayer = "playerDS"; String aliasParent = "parentsDS"; String aliasChildren = "childrenDS"; DataSource parentsDS = DataSource.database(database).as(aliasParent); DataSource playerDS = DataSource.database(database).as(aliasPlayer); DataSource childrenDS = DataSource.database(database).as(aliasChildren); Expression expression = Expression.property("type").from(aliasPlayer).equalTo(Expression.string("player")) .and(Expression.property("playerId").from(aliasPlayer).equalTo(Expression.intValue(playerId))) .and(Expression.property("type").from(aliasParent).equalTo(Expression.string("parent"))) .and(Expression.property("type").from(aliasChildren).equalTo(Expression.string("child"))); Query query = QueryBuilder.select( SelectResult.expression(Meta.id.from("playerDS")), SelectResult.expression(Expression.property("type").from(aliasPlayer)), SelectResult.expression(Expression.property("parentId").from(aliasPlayer)), SelectResult.expression(Expression.property("playerId").from(aliasPlayer)), SelectResult.expression(Expression.property("childId").from(aliasPlayer)), SelectResult.expression(Expression.property("parentName").from(aliasParent)), SelectResult.expression(Expression.property("childName").from(aliasChildren)) ).from(playerDS) .join( Join.join(parentsDS).on(Expression.property("parentId").from(aliasPlayer).equalTo(Expression.property("parentId").from(aliasParent))), // 修改child的关联条件,新增和player的childId匹配 Join.join(childrenDS).on(Expression.property("childId").from(aliasPlayer).equalTo(Expression.property("childId").from(aliasChildren)) // 若需要额外校验child归属的parent和player选定的parent一致,可保留下面这行条件,避免脏数据影响 .and(Expression.property("parentId").from(aliasChildren).equalTo(Expression.property("parentId").from(aliasParent)))) ) .where(expression); ResultSet resultSet = null; try { resultSet = query.execute(); logMessages(resultSet.size()); // 此时会返回预期的2条结果 } catch (CouchbaseLiteException e) { logMessages(e); } }
注意:如果你实际的child文档中唯一标识字段名不是
childId,请将上述代码中child表对应的字段名替换为你实际使用的字段即可。
内容的提问来源于stack exchange,提问作者ruth hadish
相关产品推荐
相关产品推荐

