You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by pi...@apache.org on 2018/02/15 18:43:25 UTC

[geode-examples] branch develop updated: GEODE-4440: Create an example that demonstrates OQL compact range indexes. (#48)

This is an automated email from the ASF dual-hosted git repository.

pivotalsarge pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode-examples.git


The following commit(s) were added to refs/heads/develop by this push:
     new 0d04c0b  GEODE-4440: Create an example that demonstrates OQL compact range indexes. (#48)
0d04c0b is described below

commit 0d04c0b999f304446685bca686dfe59b995cbe20
Author: Michael "Sarge" Dodge <md...@pivotal.io>
AuthorDate: Thu Feb 15 10:43:22 2018 -0800

    GEODE-4440: Create an example that demonstrates OQL compact range indexes. (#48)
    
    * GEODE-4440: Create an example that demonstrates OQL compact range indexes.
    
    * GEODE-4440: Address review comments.
    
    * GEODE-4440: Address review comment.
---
 README.md                                          |  2 +-
 indexes/README.md                                  | 57 +++++++++++++++
 indexes/scripts/start.gfsh                         | 26 +++++++
 indexes/scripts/stop.gfsh                          | 19 +++++
 .../org/apache/geode_examples/indexes/Example.java | 82 ++++++++++++++++++++++
 .../apache/geode_examples/indexes/FlightCode.java  | 54 ++++++++++++++
 .../apache/geode_examples/indexes/Passenger.java   | 66 +++++++++++++++++
 .../geode_examples/indexes/RegionPopulator.java    | 76 ++++++++++++++++++++
 settings.gradle                                    |  1 +
 9 files changed, 382 insertions(+), 1 deletion(-)

diff --git a/README.md b/README.md
index e2d67f0..07c08c9 100644
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@ tutorial.
 
 *  [Serialization](serialization/README.md)
 *  [Lucene Indexing](lucene/README.md)
-*  OQL Indexing
+*  [OQL Indexing](indexes/README.md)
 *  [Cache Loader](loader/README.md)
 *  [Cache Writer](writer/README.md)
 *  [Cache Listeners](listener/README.md)
diff --git a/indexes/README.md b/indexes/README.md
new file mode 100644
index 0000000..b8ed7a7
--- /dev/null
+++ b/indexes/README.md
@@ -0,0 +1,57 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Geode OQL Indexing Example
+
+This example demonstrates an index for OQL
+[queries](https://geode.apache.org/docs/guide/11/developing/query_index/query_index.html)
+on a region.
+
+A region can contain objects of arbitrary complexity, including objects that contain other objects.
+The values of a region can be queried using
+[OQL](https://geode.apache.org/docs/guide/11/developing/querying_basics/chapter_overview.html) and
+OQL queries can reference fields in the objects in the region. Indexes can be created to improve
+the performance of queries. Certain optimizations occur for top-level fields but indexes can also be
+created for nested fields, i.e., fields of objects that are contained with the objects in the
+region.
+
+This example uses a mock database of passengers and flights stored in a single region. Since the
+region contains passenger objects, the index on passenger name uses a top-level field.
+Since flight code objects are contained within a passenger object, the index on airline code uses a
+nested field. After randomly populating the mock database, this example shows the results of queries
+that use no index, a top-level index, and a nested index.
+
+This example assumes that Java and Geode are installed.
+
+## Steps
+
+1. From the `geode-examples/indexes` directory, build the example and
+   run unit tests.
+
+        $ ../gradlew build
+
+2. Next start the locator and two servers.
+
+        $ gfsh run --file=scripts/start.gfsh
+
+3. Run the example to create indexes in the region.
+
+        $ ../gradlew run
+
+4. Shut down the system.
+
+        $ gfsh run --file=scripts/stop.gfsh
diff --git a/indexes/scripts/start.gfsh b/indexes/scripts/start.gfsh
new file mode 100644
index 0000000..1a2e3ae
--- /dev/null
+++ b/indexes/scripts/start.gfsh
@@ -0,0 +1,26 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+start locator --name=locator --bind-address=127.0.0.1
+start server --name=server1 --locators=127.0.0.1[10334] --server-port=0 --classpath=../build/classes/main
+start server --name=server2 --locators=127.0.0.1[10334] --server-port=0 --classpath=../build/classes/main
+list members
+
+create region --name=example-region --type=REPLICATE --skip-if-exists=true
+create index --name=topLevelIndex --expression=name --region=/example-region
+create index --name=nestedIndex --expression=flight.airlineCode --region=/example-region
+describe region --name=example-region
diff --git a/indexes/scripts/stop.gfsh b/indexes/scripts/stop.gfsh
new file mode 100644
index 0000000..15cd93c
--- /dev/null
+++ b/indexes/scripts/stop.gfsh
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+connect --locator=127.0.0.1[10334]
+shutdown --include-locators=true
diff --git a/indexes/src/main/java/org/apache/geode_examples/indexes/Example.java b/indexes/src/main/java/org/apache/geode_examples/indexes/Example.java
new file mode 100644
index 0000000..5f14964
--- /dev/null
+++ b/indexes/src/main/java/org/apache/geode_examples/indexes/Example.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode_examples.indexes;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.client.ClientRegionFactory;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.cache.query.FunctionDomainException;
+import org.apache.geode.cache.query.NameResolutionException;
+import org.apache.geode.cache.query.QueryInvocationTargetException;
+import org.apache.geode.cache.query.QueryService;
+import org.apache.geode.cache.query.SelectResults;
+import org.apache.geode.cache.query.TypeMismatchException;
+
+public class Example {
+  static String REGIONNAME = "example-region";
+  static String NON_INDEXED_QUERY = "SELECT DISTINCT * FROM /" + REGIONNAME;
+  static String TOP_LEVEL_INDEX_QUERY =
+      "SELECT DISTINCT * FROM /" + REGIONNAME + " p WHERE p.name LIKE $1";
+  static String NESTED_INDEX_QUERY =
+      "SELECT DISTINCT * FROM /" + REGIONNAME + " p WHERE p.flight.airlineCode=$1";
+
+  public static void main(String[] args) {
+    // connect to the locator using default port 10334
+    ClientCache cache = new ClientCacheFactory().addPoolLocator("127.0.0.1", 10334)
+        .set("log-level", "WARN").create();
+
+    Example example = new Example();
+
+    // create a local region that matches the server region
+    ClientRegionFactory<String, Passenger> clientRegionFactory =
+        cache.createClientRegionFactory(ClientRegionShortcut.PROXY);
+    Region<String, Passenger> region = clientRegionFactory.create("example-region");
+    QueryService queryService = cache.getQueryService();
+
+    RegionPopulator populator = new RegionPopulator();
+    populator.populateRegion(region);
+
+    System.out.println("Total number of passengers: "
+        + example.countResults(queryService, NON_INDEXED_QUERY, new Object[] {}));
+    for (String lastName : populator.lastNames) {
+      System.out.println("Flights for " + lastName + ": " + example.countResults(queryService,
+          TOP_LEVEL_INDEX_QUERY, new Object[] {"%" + lastName}));
+    }
+    for (String airline : populator.airlines) {
+      System.out.println("Flights for " + airline + ": "
+          + example.countResults(queryService, NESTED_INDEX_QUERY, new Object[] {airline}));
+    }
+
+    cache.close();
+  }
+
+  int countResults(QueryService queryService, String queryString, Object[] params) {
+    try {
+      int count = 0;
+      SelectResults<Passenger> results =
+          (SelectResults<Passenger>) queryService.newQuery(queryString).execute(params);
+      for (Passenger passenger : results) {
+        ++count;
+      }
+      return count;
+    } catch (FunctionDomainException | TypeMismatchException | NameResolutionException
+        | QueryInvocationTargetException e) {
+      e.printStackTrace();
+      return -1;
+    }
+  }
+}
diff --git a/indexes/src/main/java/org/apache/geode_examples/indexes/FlightCode.java b/indexes/src/main/java/org/apache/geode_examples/indexes/FlightCode.java
new file mode 100644
index 0000000..1a4d7fa
--- /dev/null
+++ b/indexes/src/main/java/org/apache/geode_examples/indexes/FlightCode.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode_examples.indexes;
+
+import java.io.Serializable;
+
+public class FlightCode implements Serializable {
+  private static final long serialVersionUID = -4252046061229265115L;
+
+  String airlineCode;
+  int flightNumber;
+  String departure;
+  String arrival;
+
+  public FlightCode(String airlineCode, int flightNumber, String departure, String arrival) {
+    this.airlineCode = airlineCode;
+    this.flightNumber = flightNumber;
+    this.departure = departure;
+    this.arrival = arrival;
+  }
+
+  public String getAirlineCode() {
+    return airlineCode;
+  }
+
+  public int getFlightNumber() {
+    return flightNumber;
+  }
+
+  public String getDeparture() {
+    return departure;
+  }
+
+  public String getArrival() {
+    return arrival;
+  }
+
+  public String toString() {
+    return getAirlineCode() + String.format("%03d", getFlightNumber()) + " from " + getDeparture()
+        + " to " + getArrival();
+  }
+}
diff --git a/indexes/src/main/java/org/apache/geode_examples/indexes/Passenger.java b/indexes/src/main/java/org/apache/geode_examples/indexes/Passenger.java
new file mode 100644
index 0000000..aabfc06
--- /dev/null
+++ b/indexes/src/main/java/org/apache/geode_examples/indexes/Passenger.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode_examples.indexes;
+
+import java.io.Serializable;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class Passenger implements Serializable {
+  private static final long serialVersionUID = -991115968572408216L;
+  static final DateFormat ISO_8601_TIMESTAMP_FORMAT =
+      new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
+
+  String name;
+  int age;
+  FlightCode flight;
+  Date departure;
+  Date arrival;
+
+  public Passenger(String name, int age, FlightCode flight, Date departure, Date arrival) {
+    this.name = name;
+    this.age = age;
+    this.flight = flight;
+    this.departure = departure;
+    this.arrival = arrival;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public int getAge() {
+    return age;
+  }
+
+  public FlightCode getFlight() {
+    return flight;
+  }
+
+  public Date getDeparture() {
+    return departure;
+  }
+
+  public Date getArrival() {
+    return arrival;
+  }
+
+  public String toString() {
+    return getName() + ", age " + getAge() + ", flight " + getFlight() + ", departing at "
+        + ISO_8601_TIMESTAMP_FORMAT.format(getDeparture()) + ", arriving at "
+        + ISO_8601_TIMESTAMP_FORMAT.format(getArrival());
+  }
+}
diff --git a/indexes/src/main/java/org/apache/geode_examples/indexes/RegionPopulator.java b/indexes/src/main/java/org/apache/geode_examples/indexes/RegionPopulator.java
new file mode 100644
index 0000000..bc2edea
--- /dev/null
+++ b/indexes/src/main/java/org/apache/geode_examples/indexes/RegionPopulator.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode_examples.indexes;
+
+import org.apache.geode.cache.Region;
+
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.PrimitiveIterator;
+import java.util.Random;
+
+public class RegionPopulator {
+  static final String[] airlines = "FFT,NKS,ASQ,AAL,UAL,SKW,SWA,HAL,JBU,VRD,DAL,ASA,EIA".split(",");
+  static final String[] cities =
+      "Arendelle City,SzohĂ´d,Portland,Elbonia City,Florin City,Edelweiss,Doomstadt,Markovburg,Parador City,Rio Lindo"
+          .split(",");
+  static final String[] firstNames =
+      "Ava,Brooklyn,Charlotte,Delilah,Emma,Faith,Grace,Harper,Isabella,Julia,Kaylee,Lillian,Mia,Natalie,Olivia,Peyton,Quinn,Riley,Sophia,Taylor,Unique,Victoria,Willow,Ximena,Yaretzi,Zoey"
+          .split(",");
+  static final String[] lastNames =
+      "Smith,Johnson,Williams,Brown,Jones,Miller,Davis,Garcia,Rodriguez,Wilson,Martinez,Anderson,Taylor,Thomas,Hernandez,Moore,Martin,Jackson,Thompson,White,Lopez,Lee,Gonzalez,Harris,Clark,Lewis"
+          .split(",");
+  final Random random = new Random();
+  final LinkedList<FlightCode> flights = new LinkedList<>();
+
+  void populateRegion(Region<String, Passenger> region) {
+    populateFlights(50);
+    insertPassengers(250, region);
+  }
+
+  void populateFlights(int numberOfFlights) {
+    PrimitiveIterator.OfInt flightNumbers = random.ints(1, 1000).iterator();
+    PrimitiveIterator.OfInt airlineIndexes = random.ints(0, airlines.length).iterator();
+    PrimitiveIterator.OfInt cityIndexes = random.ints(0, cities.length).iterator();
+    while (flights.size() < numberOfFlights) {
+      String departure = cities[cityIndexes.next()];
+      String arrival = cities[cityIndexes.next()];
+      while (departure.equals(arrival)) {
+        arrival = cities[cityIndexes.next()];
+      }
+      FlightCode flight =
+          new FlightCode(airlines[airlineIndexes.next()], flightNumbers.next(), departure, arrival);
+      flights.add(flight);
+    }
+  }
+
+  void insertPassengers(int numberOfPassengers, Region<String, Passenger> region) {
+    PrimitiveIterator.OfInt firstNameIndexes = random.ints(0, firstNames.length).iterator();
+    PrimitiveIterator.OfInt lastNameIndexes = random.ints(0, lastNames.length).iterator();
+    PrimitiveIterator.OfInt ages = random.ints(20, 100).iterator();
+    PrimitiveIterator.OfInt flightIndexes = random.ints(0, flights.size()).iterator();
+    PrimitiveIterator.OfInt milliSeconds = random.ints(0, 7 * 24 * 60 * 60 * 1000).iterator();
+    while (region.sizeOnServer() < numberOfPassengers) {
+      String name = firstNames[firstNameIndexes.next()] + " " + lastNames[lastNameIndexes.next()];
+      if (!region.containsKey(name)) {
+        final long departure = System.currentTimeMillis() + milliSeconds.next();
+        final long arrival = departure + milliSeconds.next();
+        Passenger passenger = new Passenger(name, ages.next(), flights.get(flightIndexes.next()),
+            new Date(departure), new Date(arrival));
+        region.put(passenger.getName(), passenger);
+      }
+    }
+  }
+}
diff --git a/settings.gradle b/settings.gradle
index dbec67e..d23bb7e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -32,3 +32,4 @@ include 'luceneSpatial'
 include 'eviction'
 include 'serialization'
 include 'expiration'
+include 'indexes'

-- 
To stop receiving notification emails like this one, please contact
pivotalsarge@apache.org.