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.