Search code examples
ignite

Not able to find database while joining 2 cache in ignite


I am working on utilizing distributed joins between multiple ignite cache. I loaded the required data in both the caches and while performing the join it fails while parsing the SQL suggesting "Database not found" (Please see the stack trace).

Caused by: org.h2.jdbc.JdbcSQLException: Database "OFFER" not found; SQL statement:
SELECT "customOrganizationCache".Organization._key, "customOrganizationCache".Organization._val from Organization as organization, "customOfferCache".Offer as offer where organization._id = offer.relationships.customer.targets.key and organization._id = ? [90013-191]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
at org.h2.message.DbException.get(DbException.java:179)

Below is my ignite config file:

<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="offerCacheStoreFactory" class="javax.cache.configuration.FactoryBuilder" factory-method="factoryOf">
<constructor-arg><value>com.xyz.exploreignite.cache.CustomOfferCacheStore</value></constructor-arg>
</bean>

<bean id="organizationCacheStoreFactory" class="javax.cache.configuration.FactoryBuilder" factory-method="factoryOf">
<constructor-arg><value>com.xyz.exploreignite.cache.CustomOrganizationCacheStore</value></constructor-arg>
</bean>

<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
    <property name="peerClassLoadingEnabled" value="false"/>
<property name="clientMode" value="false"/>
<property name="gridName" value="clusterGrid"/>
    <property name="cacheConfiguration">
        <list>               
    <bean class="org.apache.ignite.configuration.CacheConfiguration">
                <property name="atomicityMode" value="ATOMIC"/>
                <property name="backups" value="1"/>
                <property name="name" value="customOrganizationCache"/>
                <property name="readThrough" value="true"/>
                <property name="writeThrough" value="true"/>
                <property name="cacheMode" value="PARTITIONED"/>
                <property name="writeBehindEnabled" value="true"/>
                <property name="copyOnRead" value="false"/>
                <property name="memoryMode" value="OFFHEAP_TIERED"/>
                <property name="atomicWriteOrderMode" value="PRIMARY"/>
                <property name="indexedTypes" >
        <list>
            <value>java.lang.String</value>
            <value>com.xyz.exploreignite.pojo.Organization</value>
        </list>
        </property>
        <!-- Cache store. -->
        <property name="cacheStoreFactory" ref="organizationCacheStoreFactory"/>
        <property name="swapEnabled" value="false"/>
        <property name="offHeapMaxMemory" value="0"/>
        <property name="evictionPolicy">
        <!-- LRU eviction policy. -->
        <bean class="org.apache.ignite.cache.eviction.lru.LruEvictionPolicy">
            <!-- Set the maximum cache size to 1 million (default is 100,000). -->
            <property name="maxSize" value="1000000"/>
        </bean>
        </property>
            </bean>
    <bean class="org.apache.ignite.configuration.CacheConfiguration">
                <property name="atomicityMode" value="ATOMIC"/>
                <property name="backups" value="1"/>
                <property name="name" value="customOfferCache"/>
                <property name="readThrough" value="true"/>
                <property name="writeThrough" value="true"/>
                <property name="cacheMode" value="PARTITIONED"/>
                <property name="writeBehindEnabled" value="true"/>
                <property name="copyOnRead" value="false"/>
                <property name="memoryMode" value="OFFHEAP_TIERED"/>
                <property name="atomicWriteOrderMode" value="PRIMARY"/>
                <property name="indexedTypes" >
        <list>
            <value>java.lang.String</value>
            <value>com.xyz.exploreignite.pojo.Offer</value>
        </list>
        </property>
        <!-- Cache store. -->
        <property name="cacheStoreFactory" ref="offerCacheStoreFactory"/>
        <property name="swapEnabled" value="false"/>
        <property name="offHeapMaxMemory" value="0"/>
        <property name="evictionPolicy">
        <!-- LRU eviction policy. -->
        <bean class="org.apache.ignite.cache.eviction.lru.LruEvictionPolicy">
            <!-- Set the maximum cache size to 1 million (default is 100,000). -->
            <property name="maxSize" value="1000000"/>
        </bean>
        </property>
            </bean>
        </list>
    </property>


    <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. -->
    <property name="discoverySpi">
        <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
            <property name="ipFinder">
                <!--
                    Ignite provides several options for automatic discovery that can be used
                    instead os static IP based discovery. For information on all options refer
                    to our documentation: http://apacheignite.readme.io/docs/cluster-config
                -->
                <!-- Uncomment static IP finder to enable static-based discovery of initial nodes. -->
                <!--<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">-->
                <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
                    <property name="addresses">
                        <list>
                            <value>127.0.0.1:47500..47509</value>
                        </list>
                    </property>
                </bean>
            </property>
        </bean>
    </property>
</bean>

Below is the code that I am using while performing the join:

try (Ignite ignite = Ignition.start(
            // "/home/impadmin/ignite/apache-ignite-fabric-1.7.0-bin/examples/config/example-cache-ss-cluster.xml"))
            // {
            "/home/xyz/msheth/install/apache-ignite-fabric-1.7.0-bin/examples/config/example-cache-ss-cluster.xml")) {

        try (IgniteCache<String, Offer> customOfferCache = ignite.getOrCreateCache("customOfferCache");

                IgniteCache<String, Organization> customOrganizationCache = ignite
                        .getOrCreateCache("customOrganizationCache")) {


            SqlFieldsQuery joinQuery = new SqlFieldsQuery("select organization.displayName "
                    + "from Organization as organization, \"customOfferCache\".Offer as offer"
                    + " where organization._id = offer.relationships.customer.targets.key "
                    + "and organization._id = ?");

            joinQuery.setDistributedJoins(true);

            long startTime = System.currentTimeMillis();
            try (QueryCursor<List<?>> joinCursor = customOrganizationCache
                    .query(joinQuery.setArgs("542de0b83b2d445f0a0e0f53"))) {
                for (List<?> organizationEntry : joinCursor)
                    System.out.println("Organizations display name: " + organizationEntry);
            }

            System.out.println("Time to fetch join based record:" + (System.currentTimeMillis() - startTime));

        }

    }

Please help me to find the root cause.


Solution

  • The issue is in this expression:

    offer.relationships.customer.targets.key
    

    Couple of considerations around this:

    • You are allowed to have nested objects, however Ignite will create flat schema. E.g., customer field can be accessed as a member of Offer table, you should not provide this full path for this. Generally, you should try to avoid nested object when using SQL and create simple POJO classes instead.
    • However, you are not allowed to query inside a collection. In your case the whole collection of targets is saved as a single object and you can't select based on its contents. You should have separate cache for Target objects and join it with other tables.