如何通过子对象唯一值或值集访问Gemfire对象?

时间:2015-01-27 19:43:18

标签: gemfire spring-data-gemfire

我有一种情况,我在Gemfire中存储一个复杂的对象。为简单起见,它是一个具有多个属性的客户对象。我们还存储了一个电子邮件地址对象列表(不仅仅是电子邮件字符串),地址,电话号码以及对“外国系统”的引用,以确定查询数据的最佳方式。

首先是对象结构(为简单起见,伪xsd)

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="customer">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="firstName" type="xs:string"/>
      <xs:element name="lastName" type="xs:string"/>
      ...
      <xs:element name="emailAddresses" type="emailAddressType" minOccurs="1"/> <!-- one or more -->
      <xs:element name="foreignSystemIdentifiers" type="foreignSystemIdentifierType"/> <!-- zero or more -->
      ...
    </xs:sequence>
  </xs:complexType>
</xs:element>
<xs:element name="emailAddressType">
    <xs:complexType>
        <xs:element name="emailAddress" type="xs:string"/>
        <xs:element name="addressType" type="xs:string"/>
        ...
    </xs:complexType>
</xs:element>
<xs:element name="foreignSystemIdentifierType">
    <xs:complexType>
        <xs:element name="foreignSystemName" type="xs:string"/>
        <xs:element name="foreignSystemId" type="xs:string"/>
        ...
    </xs:complexType>
</xs:element>
</xs:schema>

由于各种原因,我们将这些数据存储在一个区域中作为Customer对象,因此我们的用例不能接受托管或类似的概念(尽管这会使这更加简单)

需求

  • 通过唯一的电子邮件地址访问客户(全球唯一且在插入之前经过验证)
  • 通过外国系统标识符名称和ID的唯一组合访问客户(再次全局唯一且在插入之前验证)

如果需要,我们可以访问Elasticsearch,但我们真的希望通过直接返回Customer对象来解决这两个唯一的get请求。在Gemfire中解决这个问题的最佳方法是什么? FWIW,我们也在使用Spring-Data-Gemfire。

2 个答案:

答案 0 :(得分:1)

最简单的情况是使用查询(GemFire OQL)来获取所需内容......

SELECT c FROM /Customers c, c.emailAddresses e WHERE e.emailAddress = $1

免责声明:我没有测试过该查询,但我认为这应该可行。

此外,感知电子邮件地址已经过验证并保证是唯一的,您可以在此字段上添加索引,以便更快地进行搜索。

然后使用Spring Data GemFire,添加Spring Data Repository方法非常简单,例如......

public interface CustomersRepository extends GemfireRepository<Customer, Long> {

  ...

  @Query("SELECT c FROM /Customers c, c.emailAddresses e WHERE e.emailAddress = $1")
  Customer findByEmailAddress(String emailAddrdess);

}

然后从你的服务方法......

@Service
public class CustomerService {
  ...
  public Customer lookupBy(String emailAddress) {
    ...
    return customerRepo.findByEmailAddress(emailAddress);
  }
}

希望这会有所帮助(并回答你的问题)。

答案 1 :(得分:0)

    @Query("SELECT c FROM /region c, c.emailAddresses email WHERE email.emailAddress = $1")
    List<CustomerEntity> findByEmailAddress(String emailAddress);

这部分用堆栈跟踪炸毁:

引起:java.lang.ClassCastException:com.gemstone.gemfire.cache.query.internal.Undefined无法强制转换为com.gemstone.gemfire.cache.query.SelectResults

我的查询有什么问题?