首页 > 解决方案 > 通过部分键查询 GemFire 区域

问题描述

当 key 是 GemFire Region 中 id1、id2 的组合并且 Region 用 id1 分区时,获取 key 匹配 id1 的所有行的最佳方法是什么。

我们正在考虑的几个选项:

  1. 在 id1 上创建另一个索引。如果我们这样做,我们想知道它是否违反所有分区区域?

  2. 将数据感知函数和过滤器(id1,null)写入目标特定分区区域。通过使用在本地区域中使用索引QueryService

如果有其他方法可以通过部分键实现查询,请告诉我。

标签: gemfirespring-data-gemfire

解决方案


好吧,它可以通过在上面的“选项”中使用 #1 和 #2 的组合来实现(最佳)(取决于您的应用程序域对象是否也存储/引用了密钥,如果您使用的是 SD [G] 存储库。

这可能最好通过文档和示例来解释,特别是使用PartitionResolver接口Javadoc

假设您的“复合”键实现如下:

class CompositeKey implements PartitionResolver {

  private final Object idOne;
  private final Object idTwo;

  CompositeKey(Object idOne, Object idTwo) {
    // argument validation as necessary
    this.idOne = idOne;
    this.idTwo = idTwo;
  }

  public String getName() {
    return "MyCompositeKeyPartitionResolver";
  }

  public Object getRoutingObject() {
    return idOne;
  }
}

然后,您可以调用一个函数来查询您想要的结果,方法是使用...

Execution execution = FunctionService.onRegion("PartitionRegionName");

或者,您可以在调用函数时使用返回Execution来过滤您想要查询(进一步限定)的(复杂)键...

ComplexKey filter = { .. };

execution.withFilter(Arrays.stream(filter).collect(Collectors.toSet()));

当然,如果您事先不知道您的密钥,这是有问题的。

然后您可能更喜欢使用 ComplexKey 来识别您的应用程序域对象,这在使用 SD[G] 的存储库抽象/扩展时是必需的:

@Region("MyPartitionRegion")
class ApplicationDomainObject {

  @Id
  CompositeKey identifier;

  ...
}

然后,您可以编写您的函数以对分区区域的“本地数据集”进行操作。也就是说,当集群中的一个数据节点托管相同的分区区域(PR)时,它只会对该 PR 的“桶”中的数据集进行操作,这通过执行以下操作来完成:

class QueryPartitionRegionFunction implements Function {

  public void execute(FunctionContext<Object> functionContext) {

    RegionFunctionContext regionFunctionContext = 
      (RegionFunctionContext) functionContext;

    Region<ComplexKey, ApplicationDomainObject> localDataSet =
      PartitionRegionHelper.getLocalDataForContext(regionFunctionContext);

    SelectResults<?> resultSet = 
      localDataSet.query(String.format("identifier.idTwo = %s", 
        regionFunctionContext.getArguments);

    // process result set and use ResultSender to send results

  }
}

当然,使用SDG 的函数注释支持(即无论如何实现和调用你的函数),所有这些都更容易做到。

请注意,当您调用 时FunctiononRegion使用 GemFireFunctionService或更方便地使用 SDG 对函数执行的注释支持,如下所示:

@OnRegion("MyPartitionRegion")
interface MyPartitionRegionFunctions {

    @FunctionId("QueryPartitionRegion")
    <return-type> queryPartitionRegion(..);

}

然后..

Object resultSet = myPartitionRegionFunctions.queryPartitionRegion(..);

然后,FunctionContext将是一个RegionFunctionContext(因为您在 PR 上执行了函数,该函数在托管 PR 的集群中的所有节点上执行)。

此外,您使用 PartitionRegionHelper.getLocalDataForContext(:RegionFunctionContext) 来获取 PR 的本地数据集(即存储桶,或者只是该节点托管的整个 PR(跨所有节点)中的数据分片,这将基于你的“习惯” PartitionResolver)。

然后,您可以查询以进一步限定或过滤感兴趣的数据。您可以看到我通过 查询(或进一步限定)idTwo,这不是PartitionResolver实现的一部分。此外,如果您没有在过滤器中指定键Execution(因为我认为这将考虑整个“键”(idOne 和 idTwo),则仅在 (OQL) 查询谓词中需要),基于我们的你的类的正确实现Object.equals()的方法ComplexKey)。

但是,如果您事先不知道密钥和/或(特别是如果)您正在使用 SD[G] 的存储库,那么这ComplexKey将成为您的应用程序域 abject 的一部分,然后您可以对其进行索引和查询(如上图所示:)identifier.idTwo = ?

希望这可以帮助!

注意:我没有对此进行任何测试,但希望它能为您指明正确的方向和/或为您提供进一步的想法。


推荐阅读