Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 8A533200D26 for ; Fri, 6 Oct 2017 00:03:23 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 88593160BDB; Thu, 5 Oct 2017 22:03:23 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 076DC1609E2 for ; Fri, 6 Oct 2017 00:03:21 +0200 (CEST) Received: (qmail 72823 invoked by uid 500); 5 Oct 2017 22:03:21 -0000 Mailing-List: contact commits-help@geode.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@geode.apache.org Delivered-To: mailing list commits@geode.apache.org Received: (qmail 72770 invoked by uid 99); 5 Oct 2017 22:03:21 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 05 Oct 2017 22:03:21 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id BED7681A6F; Thu, 5 Oct 2017 22:03:18 +0000 (UTC) Date: Thu, 05 Oct 2017 22:03:18 +0000 To: "commits@geode.apache.org" Subject: [geode] branch feature/GEODE-3244 updated: GEODE-3244: provide a build in LuceneSerializer that flattens objects MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <150724099875.1200.313707731465634305@gitbox.apache.org> From: zhouxj@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: geode X-Git-Refname: refs/heads/feature/GEODE-3244 X-Git-Reftype: branch X-Git-Oldrev: 215d56e4fac3341603bdf45d7402ac7f242c0e29 X-Git-Newrev: 315367200548f6bd0816c819897af09a74873b00 X-Git-Rev: 315367200548f6bd0816c819897af09a74873b00 X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated archived-at: Thu, 05 Oct 2017 22:03:23 -0000 This is an automated email from the ASF dual-hosted git repository. zhouxj pushed a commit to branch feature/GEODE-3244 in repository https://gitbox.apache.org/repos/asf/geode.git The following commit(s) were added to refs/heads/feature/GEODE-3244 by this push: new 3153672 GEODE-3244: provide a build in LuceneSerializer that flattens objects 3153672 is described below commit 315367200548f6bd0816c819897af09a74873b00 Author: zhouxh AuthorDate: Thu Oct 5 15:01:59 2017 -0700 GEODE-3244: provide a build in LuceneSerializer that flattens objects --- .../geode/cache/lucene/LuceneSerializer.java | 1 + .../repository/serializer/FieldsWithPrefix.java} | 35 ++- .../serializer/FlatFormatSerializer.java | 295 +++++++++++++++++++++ .../serializer/ReflectionLuceneSerializer.java | 10 +- .../NestedObjectSeralizerIntegrationTest.java | 130 +++++++++ .../apache/geode/cache/lucene/test/Customer.java} | 35 ++- .../org/apache/geode/cache/lucene/test/Page.java} | 41 +-- .../apache/geode/cache/lucene/test/Person.java} | 43 +-- 8 files changed, 508 insertions(+), 82 deletions(-) diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java index 363867d..ceebc65 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java +++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java @@ -32,6 +32,7 @@ public interface LuceneSerializer extends Declarable { * Add the fields of the given value to a set of documents * * @param index lucene index + * @param value user object to be serialized into index */ Collection toDocuments(LuceneIndex index, Object value); } diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/repository/serializer/FieldsWithPrefix.java similarity index 59% copy from geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java copy to geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/repository/serializer/FieldsWithPrefix.java index 363867d..cc40439 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java +++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/repository/serializer/FieldsWithPrefix.java @@ -4,34 +4,29 @@ * 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.cache.lucene.internal.repository.serializer; -package org.apache.geode.cache.lucene; +import java.util.HashSet; -import java.util.Collection; +public class FieldsWithPrefix { + HashSet topLevelFieldSet; + String prefix; -import org.apache.geode.cache.Declarable; -import org.apache.lucene.document.Document; + FieldsWithPrefix(HashSet topLevelFieldSet, String prefix) { + this.topLevelFieldSet = topLevelFieldSet; + this.prefix = prefix; + } -import org.apache.geode.annotations.Experimental; - -/** - * An interface for writing the fields of an object into a lucene document - */ -@Experimental -public interface LuceneSerializer extends Declarable { - - /** - * Add the fields of the given value to a set of documents - * - * @param index lucene index - */ - Collection toDocuments(LuceneIndex index, Object value); + @Override + public String toString() { + return "prefix is " + prefix + ", topLevelFieldSet is " + topLevelFieldSet; + } } diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/repository/serializer/FlatFormatSerializer.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/repository/serializer/FlatFormatSerializer.java new file mode 100644 index 0000000..f3bb5bd --- /dev/null +++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/repository/serializer/FlatFormatSerializer.java @@ -0,0 +1,295 @@ +/* + * 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.cache.lucene.internal.repository.serializer; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.apache.geode.cache.lucene.LuceneIndex; +import org.apache.geode.cache.lucene.LuceneSerializer; +import org.apache.geode.internal.logging.LogService; +import org.apache.geode.internal.util.concurrent.CopyOnWriteWeakHashMap; +import org.apache.geode.pdx.PdxInstance; +import org.apache.logging.log4j.Logger; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field.Store; +import org.apache.lucene.document.FieldType; +import org.apache.lucene.document.LongPoint; +import org.apache.lucene.document.TextField; +import org.apache.lucene.index.IndexableField; + +public class FlatFormatSerializer implements LuceneSerializer { + /** + * A mapper for converting a PDX object into a document + */ + private LuceneSerializer pdxMapper; + + /** + * Mappers for each individual class type that this class has seen. + * + * Weak so that entry will be removed if a class is garbage collected. + */ + private Map, LuceneSerializer> mappers = + new CopyOnWriteWeakHashMap, LuceneSerializer>(); + + /** + * keep class to defined fields mapping for each class For example, Customer object based on + * indexed fields name, contact.name, contact.address, contact.homepage.title will become + * , prefix=null)>; , prefix=contact)>, , prefix=contact.homepage)> + */ + public HashMap, FieldsWithPrefix> classToFieldsMapping = new HashMap(); + + private static final Logger logger = LogService.getLogger(); + + public FlatFormatSerializer() { + final PrimitiveSerializer primitiveSerializer = new PrimitiveSerializer(); + SerializerUtil.supportedPrimitiveTypes().stream() + .forEach(type -> mappers.put(type, primitiveSerializer)); + + pdxMapper = new PdxLuceneSerializer(); + } + + @Override + public Collection toDocuments(LuceneIndex index, Object value) { + if (value == null) { + return Collections.emptyList(); + } + + LuceneSerializer mapper = getFieldMapper(value, index.getFieldNames()); + + Collection docs = mapper.toDocuments(index, value); + if (logger.isDebugEnabled()) { + logger.debug("FlatFormatSerializer.toDocuments:" + docs); + } + + return docs; + } + + /** + * Get the field mapper based on the type of the given object. + */ + public LuceneSerializer getFieldMapper(Object value, String[] indexedFields) { + if (value instanceof PdxInstance) { + return FlatFormatSerializer.this.pdxMapper; + } else { + Class clazz = value.getClass(); + LuceneSerializer mapper = null; + synchronized (mappers) { + mapper = mappers.get(clazz); + if (mapper == null) { + // parse this nested object (i.e. customerObject) to build class-fields map for each field + // At this time, the parameters are (customerObject, ) + // create classToFields mapping for value's class + // finally classToFieldsMapping will contain: + // >, >, + // > + createClassToFieldsMapping(value, indexedFields, null); + + // search in current mappers for all the classes used in this nested object + for (Map.Entry, FieldsWithPrefix> entry : classToFieldsMapping.entrySet()) { + Class aClassWithIndexedFields = entry.getKey(); + if (mappers.get(aClassWithIndexedFields) == null) { + // if the class is still not in mappers, and it contains non-nested fields, just + // create + // ReflectionLuceneSerializer + HashSet topLevelFieldSet = entry.getValue().topLevelFieldSet; + String prefix = entry.getValue().prefix; + String[] fields = topLevelFieldSet.toArray(new String[topLevelFieldSet.size()]); + + // parameters are (Customer.class, ) + mapper = + new FlatFormatReflectionLuceneSerializer(aClassWithIndexedFields, fields, prefix); + mappers.put(aClassWithIndexedFields, mapper); + } + } + return mappers.get(clazz); + } else { + return mapper; + } + } + } + } + + /* + * create value's class to its indexed fields mapping + */ + private void createClassToFieldsMapping(Object value, String[] indexedFields, String prefix) { + Class clazz = value.getClass(); + FieldsWithPrefix fieldsWithPrefix = classToFieldsMapping.get(clazz); + if (fieldsWithPrefix == null) { + HashSet topLevelFieldSet = new HashSet(); + fieldsWithPrefix = new FieldsWithPrefix(topLevelFieldSet, prefix); + classToFieldsMapping.put(clazz, fieldsWithPrefix); + } else { + return; + } + if (logger.isDebugEnabled()) { + logger.debug("createClassToFieldsMapping:found an undefined class, object value is " + value + + ":indexedFields are " + Arrays.toString(indexedFields) + ", prefix is " + prefix); + } + + // parent field (e.g. contact) to child fields is a 1:N mapping, + // such as contact to + HashMap> parentToChildFieldsMapping = new HashMap(); + for (String f : indexedFields) { + int firstDot = f.indexOf("."); + if (firstDot != -1) { + // found a parent-child field + String parentFieldName = f.substring(0, firstDot); + String childFieldName = f.substring(firstDot + 1); + HashSet childFieldSet = parentToChildFieldsMapping.get(parentFieldName); + if (childFieldSet == null) { + childFieldSet = new HashSet(); + parentToChildFieldsMapping.put(parentFieldName, childFieldSet); + } + childFieldSet.add(childFieldName); + + fieldsWithPrefix.topLevelFieldSet.add(parentFieldName); + } else { + // only found a top level field + fieldsWithPrefix.topLevelFieldSet.add(f); + } + } + if (logger.isDebugEnabled()) { + logger.info("createClassToFieldsMapping:topLevelFieldSet is " + + fieldsWithPrefix.topLevelFieldSet + ":prefix is " + prefix + + ":parentToChildFieldsMap is " + parentToChildFieldsMapping); + } + + // Now we've got a topLevelFieldSet, such as and a parentToChildFieldsMapping + // such as > + // for each parent field, i.e. contact, recursively process with its childFieldSet, i.e. + for (Map.Entry> entry : parentToChildFieldsMapping.entrySet()) { + try { + String parentFieldName = entry.getKey(); + HashSet childFieldSet = entry.getValue(); + String[] childFields = childFieldSet.toArray(new String[childFieldSet.size()]); + + // parentFieldName is to get childValue + Object childValue = getFieldValue(value, parentFieldName); + + // now we've got a child object, find class-fields mapping for its fields + // this time, the parameters are (personObject, ) + createClassToFieldsMapping(childValue, childFields, parentFieldName); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private Object getFieldValue(Object parentValue, String parentFieldName) + throws NoSuchFieldException, SecurityException { + // now check if there's grandchild in nestedFields + Class parentClazz = parentValue.getClass(); + Field field = parentClazz.getDeclaredField(parentFieldName); + Object childValue = null; + try { + field.setAccessible(true); + childValue = field.get(parentValue); + } catch (Exception e) { + e.printStackTrace(System.out); + } + return childValue; + } + + class FlatFormatReflectionLuceneSerializer extends ReflectionLuceneSerializer { + + String prefix; + + public FlatFormatReflectionLuceneSerializer(Class clazz, + String[] indexedFields, String prefix) { + super(clazz, indexedFields); + this.prefix = prefix; + } + + @Override + public Collection toDocuments(LuceneIndex index, Object value) { + Document parentDoc = new Document(); + + for (Field field : fields) { + try { + field.setAccessible(true); + Object fieldValue = field.get(value); + if (fieldValue == null) { + continue; + } + Class fieldType = field.getType(); + + if (classToFieldsMapping.containsKey(fieldType)) { + // for each object field value with class defined in classToFieldsMapping, serialize it + // to a document + // then add the document's indexableFields into parentDoc + FieldsWithPrefix fieldsWithPrefix = classToFieldsMapping.get(fieldType); + HashSet topLevelFieldSet = fieldsWithPrefix.topLevelFieldSet; + String[] topLevelFieldNames = + topLevelFieldSet.toArray(new String[topLevelFieldSet.size()]); + + LuceneSerializer childSerializer = getFieldMapper(fieldValue, topLevelFieldNames); + Collection childDocs = childSerializer.toDocuments(index, fieldValue); + for (Document childDoc : childDocs) { + for (IndexableField oneDocField : childDoc.getFields()) { + parentDoc.add(addPrefixToDocumentField(oneDocField, prefix)); + } + } + } else { + SerializerUtil.addField(parentDoc, + (prefix == null ? field.getName() : prefix + "." + field.getName()), fieldValue); + } + } catch (IllegalArgumentException | IllegalAccessException e) { + if (logger.isDebugEnabled()) { + logger.debug("FlatFormatReflectionLuceneSerializer.toDocuments encountered exception", + e); + } + } + } + if (logger.isDebugEnabled()) { + logger.debug("FlatFormatReflectionLuceneSerializer.toDocuments:" + parentDoc); + } + return Collections.singleton(parentDoc); + } + + private IndexableField addPrefixToDocumentField(IndexableField oneDocField, String prefix) { + if (prefix == null) { + return oneDocField; + } + String newName = prefix + "." + oneDocField.name(); + // // do it for each field type used in SerializerUtil.addField() + if (oneDocField instanceof TextField) { + TextField newTextField = new TextField(newName, ((TextField)oneDocField).stringValue(), Store.NO); + return newTextField; + } + // TODO: we have to change field name for each field type. But LongPoint seems not straightforward. + return null; + } + + protected boolean isSupported(Class type) { + return true; + } + + @Override + public String toString() { + return "FlatFormatReflectionLuceneSerializer:prefix is " + prefix + ", fields are " + + Arrays.toString(fields); + } + } +} diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/repository/serializer/ReflectionLuceneSerializer.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/repository/serializer/ReflectionLuceneSerializer.java index 5b9298b..176d4e1 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/repository/serializer/ReflectionLuceneSerializer.java +++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/internal/repository/serializer/ReflectionLuceneSerializer.java @@ -35,9 +35,9 @@ import org.apache.geode.internal.logging.LogService; */ class ReflectionLuceneSerializer implements LuceneSerializer { - private Field[] fields; + protected Field[] fields; - private static final Logger logger = LogService.getLogger(); + protected static final Logger logger = LogService.getLogger(); public ReflectionLuceneSerializer(Class clazz, String[] indexedFields) { Set fieldSet = new HashSet(); @@ -50,7 +50,7 @@ class ReflectionLuceneSerializer implements LuceneSerializer { while (clazz != Object.class) { for (Field field : clazz.getDeclaredFields()) { Class type = field.getType(); - if (fieldSet.contains(field.getName()) && SerializerUtil.isSupported(type)) { + if (fieldSet.contains(field.getName()) && isSupported(type)) { field.setAccessible(true); foundFields.add(field); } @@ -62,6 +62,10 @@ class ReflectionLuceneSerializer implements LuceneSerializer { this.fields = foundFields.toArray(new Field[foundFields.size()]); } + protected boolean isSupported(Class type) { + return SerializerUtil.isSupported(type); + } + @Override public Collection toDocuments(LuceneIndex index, Object value) { Document doc = new Document(); diff --git a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/NestedObjectSeralizerIntegrationTest.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/NestedObjectSeralizerIntegrationTest.java new file mode 100644 index 0000000..b855d4f --- /dev/null +++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/NestedObjectSeralizerIntegrationTest.java @@ -0,0 +1,130 @@ +/* + * 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.cache.lucene; + +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.INDEX_NAME; +import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.REGION_NAME; +import static org.junit.Assert.assertEquals; + +import java.util.concurrent.TimeUnit; + +import org.apache.logging.log4j.Logger; +import org.apache.geode.cache.Region; +import org.apache.geode.cache.RegionShortcut; +import org.apache.geode.cache.lucene.internal.repository.serializer.FlatFormatSerializer; +import org.apache.geode.cache.lucene.test.Customer; +import org.apache.geode.internal.logging.LogService; +import org.apache.geode.test.junit.categories.IntegrationTest; +import org.apache.lucene.analysis.core.KeywordAnalyzer; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +@Category(IntegrationTest.class) +public class NestedObjectSeralizerIntegrationTest extends LuceneIntegrationTest { + + private static int WAIT_FOR_FLUSH_TIME = 10000; + private static final Logger logger = LogService.getLogger(); + + @Test + public void queryOnNestedObject() throws InterruptedException, LuceneQueryException { + // define index on nested objects + luceneService.createIndexFactory().setLuceneSerializer(new FlatFormatSerializer()) + .addField("name").addField("contact.name").addField("contact.email", new KeywordAnalyzer()) + .addField("contact.address").addField("contact.homepage.content") + .create(INDEX_NAME, REGION_NAME); + + Region region = createRegion(REGION_NAME, RegionShortcut.PARTITION); + + // insert a few records + region.put("object-13", new Customer("Tommy Jaskcon")); + region.put("object-14", new Customer("Johnny Jackson")); + region.put("object-15", new Customer("Johnny Jackson2")); + region.put("object-16", new Customer("Johnny Jackson21")); + + LuceneIndex index = luceneService.getIndex(INDEX_NAME, REGION_NAME); + luceneService.waitUntilFlushed(INDEX_NAME, REGION_NAME, WAIT_FOR_FLUSH_TIME, + TimeUnit.MILLISECONDS); + + // query-1: contact.name + LuceneQuery query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, + "contact.name:jackson2*", "name"); + PageableLuceneQueryResults results = query.findPages(); + assertEquals(2, results.size()); + + // query-2: name + query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, + "\"Johnni Jackson\"", "contact.name"); + results = query.findPages(); + assertEquals(1, results.size()); + printResults(results); + query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, + "\"Johnni Jackson\"", "name"); + results = query.findPages(); + printResults(results); + assertEquals(0, results.size()); + query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, + "\"Johnny Jackson\"", "name"); + results = query.findPages(); + assertEquals(1, results.size()); + printResults(results); + + // query-3: contact.email with KeywordAnalyzer + query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, + "Johnni.Jackson2@pivotal.io", "contact.email"); + results = query.findPages(); + assertEquals(1, results.size()); + printResults(results); + query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, + "Johnni.Jackson2@pivotal.io", "email"); + results = query.findPages(); + printResults(results); + assertEquals(0, results.size()); + + // query-4: contact.address with standard analyzer + query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, "97006", + "contact.address"); + results = query.findPages(); + assertEquals(4, results.size()); + printResults(results); + query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, "97006", + "address"); + results = query.findPages(); + printResults(results); + assertEquals(0, results.size()); + + // query-4: contact.homepage.title + query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, + "contact.homepage.content:Hello", "name"); + results = query.findPages(); + printResults(results); + assertEquals(4, results.size()); + query = + luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, "Hello", "title"); + results = query.findPages(); + printResults(results); + assertEquals(0, results.size()); + } + + private void printResults(PageableLuceneQueryResults results) { + if (results.size() > 0) { + while (results.hasNext()) { + results.next().stream().forEach(struct -> { + logger.info("Result is:" + struct.getValue()); + }); + } + } + } + +} diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/Customer.java similarity index 59% copy from geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java copy to geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/Customer.java index 363867d..440e0d7 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java +++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/Customer.java @@ -4,34 +4,31 @@ * 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.cache.lucene.test; -package org.apache.geode.cache.lucene; +import java.io.Serializable; -import java.util.Collection; +public class Customer implements Serializable { + private String name; + private Person contact; // search nested object -import org.apache.geode.cache.Declarable; -import org.apache.lucene.document.Document; + public Customer(String name) { + this.name = name; -import org.apache.geode.annotations.Experimental; + // purposely use Tommi instead of Tommy, Johnni instead of Johnny in contact.name + this.contact = new Person(name.replace('y', 'i')); + } -/** - * An interface for writing the fields of an object into a lucene document - */ -@Experimental -public interface LuceneSerializer extends Declarable { - - /** - * Add the fields of the given value to a set of documents - * - * @param index lucene index - */ - Collection toDocuments(LuceneIndex index, Object value); + @Override + public String toString() { + return "Customer[name=" + name + ",contact=" + contact + "]"; + } } diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/Page.java similarity index 59% copy from geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java copy to geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/Page.java index 363867d..bd0dc57 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java +++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/Page.java @@ -4,34 +4,35 @@ * 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.cache.lucene.test; -package org.apache.geode.cache.lucene; +import java.io.Serializable; -import java.util.Collection; +public class Page implements Serializable { + private int id; + private String title; + private String content; -import org.apache.geode.cache.Declarable; -import org.apache.lucene.document.Document; + public Page(int id) { + this.id = id; + if (id % 2 == 0) { + this.title = "manager"; + } else { + this.title = "developer"; + } + this.content = "Hello world no " + id; + } -import org.apache.geode.annotations.Experimental; - -/** - * An interface for writing the fields of an object into a lucene document - */ -@Experimental -public interface LuceneSerializer extends Declarable { - - /** - * Add the fields of the given value to a set of documents - * - * @param index lucene index - */ - Collection toDocuments(LuceneIndex index, Object value); + @Override + public String toString() { + return "Page[id=" + id + ",title=" + title + ",content=" + content + "]"; + } } diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/Person.java similarity index 52% copy from geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java copy to geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/Person.java index 363867d..dc7b1cf 100644 --- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/LuceneSerializer.java +++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/test/Person.java @@ -4,34 +4,37 @@ * 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.cache.lucene.test; -package org.apache.geode.cache.lucene; +import java.io.Serializable; -import java.util.Collection; +public class Person implements Serializable { + private String name; + private String email; + private int revenue; + private String address; + private Page homepage; -import org.apache.geode.cache.Declarable; -import org.apache.lucene.document.Document; + public Person(String name) { + this.name = name; + this.email = name.replace(' ', '.') + "@pivotal.io"; + int length = name.length(); + this.revenue = length * 100; + this.address = "" + length + " NW Greenbrier PKWY, Portland OR 97006"; + this.homepage = new Page(length); + } -import org.apache.geode.annotations.Experimental; - -/** - * An interface for writing the fields of an object into a lucene document - */ -@Experimental -public interface LuceneSerializer extends Declarable { - - /** - * Add the fields of the given value to a set of documents - * - * @param index lucene index - */ - Collection toDocuments(LuceneIndex index, Object value); + @Override + public String toString() { + return "Person[name=" + name + ",email=" + email + ",revenue=" + revenue + ",address=" + address + + ",homepage=" + homepage + "]"; + } } -- To stop receiving notification emails like this one, please contact ['"commits@geode.apache.org" '].