通过部分键查询GemFire区域

时间:2018-09-09 08:28:48

标签: gemfire spring-data-gemfire

如果键是GemFire区域中id1,id2的组合,并且Region被id1分区,那么获取所有键与id1匹配的行的最佳方法是什么。

我们正在考虑的选项:

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

  2. 编写数据感知功能,并按(id1,null)过滤以目标特定分区区域为目标。通过使用QueryService在本地区域中使用索引?

请问是否还有其他方法可以通过部分键实现查询。

1 个答案:

答案 0 :(得分:0)

嗯,可以通过在上面的“选项”中结合使用#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's Function annotation support(即无论如何实现和调用您的函数),所有这些操作都容易得多。

请注意,当您使用GemFire的Function调用onRegionFunctionService时,或更方便地使用SDG对函数执行的注释支持,就像这样:

@OnRegion("MyPartitionRegion")
interface MyPartitionRegionFunctions {

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

}

然后..

Object resultSet = myPartitionRegionFunctions.queryPartitionRegion(..);

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

此外,您还可以使用PartitionRegionHelper.getLocalDataForContext(:RegionFunctionContext)获取PR的本地数据集(即存储桶,或仅获取该节点托管的整个PR中(跨所有节点)的数据碎片),将基于您的“自定义” PartitionResolver)。

然后您可以查询以进一步限定或过滤感兴趣的数据。您可以看到我是由idTwo查询(或进一步限定)的,它不是PartitionResolver实现的一部分。此外,仅当您未在过滤器中使用Execution指定键时,才需要在(OQL)查询谓词中使用(因为我认为这会将整个“键”(idOne和idTwo)带入帐户,基于您的Object.equals()类的ComplexKey方法的正确实现)。

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

希望这会有所帮助!

注意:我还没有测试过任何一个,但是希望它能为您指明正确的方向和/或给您进一步的想法。