提问者:小点点

通过部分键查询GemFire区域


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

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

>

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

    编写数据感知函数并按(id1, null)过滤以定位特定的分区区域。使用QueryService在本地区域中使用索引?

    你能让我知道是否有任何其他方法来实现部分键查询。


  • 共1个答案

    匿名用户

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

    这可能最好通过文档和示例来解释,特别是使用ParttionResolver接口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来过滤您在调用Function时想要查询(进一步限定)的(复杂)键…

    ComplexKey filter = { .. };
    
    execution.withFilter(Arrays.stream(filter).collect(Collectors.toSet()));
    

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

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

    @Region("MyPartitionRegion")
    class ApplicationDomainObject {
    
      @Id
      CompositeKey identifier;
    
      ...
    }
    

    然后,您可以对Function进行编码,以对分区区域的“本地数据集”进行操作。也就是说,当集群中的数据节点托管相同的分区区域(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的Function注释支持(即无论如何都要实现和调用您的Function)更容易做到这一切。

    请注意,当您使用GemFire的FunctionService调用FunctiononRegion时,或者使用SDG对Function Execution的注释支持更方便,如下所示:

    @OnRegion("MyPartitionRegion")
    interface MyPartitionRegionFunctions {
    
        @FunctionId("QueryPartitionRegion")
        <return-type> queryPartitionRegion(..);
    
    }
    

    然后…

    Object resultSet = myPartitionRegionFunctions.queryPartitionRegion(..);
    

    然后,FunctionContext将是一个Region onFunctionContext(因为您在PR上执行了Function,它在托管PR的集群中的所有节点上执行)。

    此外,您还可以使用(: Region onFunctionContext)来获取PR的本地数据集(即存储桶,或者仅仅是该节点托管的整个PR(所有节点)中的数据分片,这将基于您的自定义分区解析器)。

    然后,您可以查询以进一步限定,或过滤感兴趣的数据。您可以看到我通过idTwo查询(或进一步限定),这不是分区解析器实现的一部分。此外,只有在(OQL)查询谓词中,如果您没有使用执行在过滤器中指定密钥(因为,我认为,这将需要整个“密钥”(idOne

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

    希望这有帮助!

    注意:我没有测试过这些,但希望它能给你指明正确的方向和/或给你进一步的想法。