0

我有一个包含 User、Message 和 MessageFeatures 等实体的应用程序。每个用户可以有许多消息,每个消息都有一个 MessageFeatures 实体。目前关系模型表示为:

User{
  UUID id
  String email
  ...
}
Message{
  UUID id,
  UUID userId
  String text
  ....
}
MessageFeatures{
  UUID id
  UUID messageId
  UUID userId
  PrimitiveObject feature1
  ....
  PrimitiveObject featureN
}

最重要的查询是:

  • 获取用户的所有消息
  • 获取用户的所有消息功能
  • 通过 uuid 获取消息
  • 通过 uuid 获取/更新消息功能
  • 通过消息 uuid 获取消息功能

不太重要(可能很慢)的查询如下:

  • 获取 user_id = someuuid 和 featureX = value 的消息特征
  • 获取 featureX = value 的所有/计数用户 uuid
  • 更新消息功能集 featureX = newValue 其中 featureX = oldValue

在评估 couchbase 时,我无法得出正确的数据模型。我不认为将用户的所有消息和消息功能放在单个文档中是一个好主意,因为大小会不断增加,并且根据当前数据,对于 2 年的数据,它很容易在 4-5 MB 的范围内。同样为了保持一致性,我一次只能更新一个消息功能,因为原子性是每个文档。

如果我不将它们放在单个文档中,它们将分散在集群中,并且诸如获取用户的所有消息/消息特征之类的查询将导致分散和聚集。

我已经检查了全局二级索引和 N1QL,但即使我索引消息的 user_uuid 字段,它也只会帮助获取该用户的 message_uuids,加载所有消息将导致分散和聚集......

有没有办法强制将 user_uuid 的所有消息、消息特征映射到同一个物理节点,而不将它们嵌入到同一个文档中,比如 redis 中的主题标签。

4

1 回答 1

1

您应该将上面的关系模型直接转换为 Couchbase。您应该为所有关系(id 字段)创建 GSI 索引。使用 EXPLAIN 确保每个查询都使用索引。要通过 id 直接查找,请使用 USE KEYS。

Couchbase 中的 Scatter/gather 与您所描述的不同。它是当单个索引扫描必须访问多个节点然后合并扫描结果(分布式索引)时。相反,每个 GSI 索引都存在于单个节点上,因此 GSI 索引避免分散/聚集。

最后,请注意 Couchbase 即使跨节点也能快速获取键值,因此您无需担心数据的局部性。

于 2015-11-12T16:31:13.413 回答