1

I have a situation where I am storing a complex object in Gemfire. For simplicity it is a customer object who has several attributes. We also store a List of email address objects (not just email strings), addresses, phone numbers, and references to "foreign systems" I need to determine the best way to query data.

First the Object Structure (pseudo xsd for simplicity)

<?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>

We are storing this data in a single region as a Customer object for various reasons, so colocation or similar concepts isn't acceptable for our use case (though it would make this infinitely simpler)

Needs

  • Access Customer by unique email address (globally unique and validated prior to insert)
  • Access Customer by unique combination of foreign system identifier name and id (again globally unique and validated prior to insert)

We do have access to Elasticsearch if needed, but we really would like to solve these two unique get requests by returning the Customer Object directly. What is the best way to solve this in Gemfire? FWIW, we are using Spring-Data-Gemfire as well.

Jeff Cook
  • 7,956
  • 36
  • 115
  • 186
fpmoles
  • 1,209
  • 8
  • 14
  • So because the email address is a nested entity, you do not have first level access to the email address string? Did i get that correct? – hubbardr Jan 27 '15 at 19:53
  • yes @hubbardr, you are correct. The same situation exists for foreign system identifier, the only difference being it is a key value pair that we need to query buy. – fpmoles Jan 27 '15 at 19:54

2 Answers2

2

The simplest case would be to use a query (GemFire OQL) to get what you need...

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

DISCLAIMER: I have not tested the query, but I think this should work.

Also, sense email address is validated and guaranteed to be unique, you could add an Index on this field to make it quicker for searching.

Then using Spring Data GemFire this is pretty straight forward to add a Spring Data Repository method, such as...

public interface CustomersRepository extends GemfireRepository<Customer, Long> {

  ...

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

}

And then from you service method...

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

Hope this helps (and answers your question).

John Blum
  • 7,381
  • 1
  • 20
  • 30
0
    @Query("SELECT c FROM /region c, c.emailAddresses email WHERE email.emailAddress = $1")
    List<CustomerEntity> findByEmailAddress(String emailAddress);

This part blows up with a stacktrace:

Caused by: java.lang.ClassCastException: com.gemstone.gemfire.cache.query.internal.Undefined cannot be cast to com.gemstone.gemfire.cache.query.SelectResults

What is wrong with my query?