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
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.
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).