You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gora.apache.org by dr...@apache.org on 2020/03/23 21:01:37 UTC
[gora] 05/07: GORA-649 MongoFilterUtil: Avoid changing query passed
as reference
This is an automated email from the ASF dual-hosted git repository.
drazzib pushed a commit to branch GORA-649-replace-deprecated-mongo-api
in repository https://gitbox.apache.org/repos/asf/gora.git
commit cfb563cc55e0b85ba9b723c9f6e03a1c2910fda8
Author: Damien Raude-Morvan <dr...@drazzib.com>
AuthorDate: Mon Mar 23 21:58:26 2020 +0100
GORA-649 MongoFilterUtil: Avoid changing query passed as reference
Return an Optional<> with subfilter to apply
---
.../gora/mongodb/filters/DefaultFactory.java | 83 ++++++++++------------
.../apache/gora/mongodb/filters/FilterFactory.java | 7 +-
.../gora/mongodb/filters/MongoFilterUtil.java | 28 ++++----
.../gora/mongodb/filters/DefaultFactoryTest.java | 41 ++++++-----
4 files changed, 76 insertions(+), 83 deletions(-)
diff --git a/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/DefaultFactory.java b/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/DefaultFactory.java
index 597f7e9..bd26209 100644
--- a/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/DefaultFactory.java
+++ b/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/DefaultFactory.java
@@ -17,19 +17,21 @@
*/
package org.apache.gora.mongodb.filters;
-import java.util.ArrayList;
-import java.util.List;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.gora.filter.*;
import org.apache.gora.mongodb.store.MongoMapping;
import org.apache.gora.mongodb.store.MongoStore;
import org.apache.gora.persistency.impl.PersistentBase;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
-import com.mongodb.QueryBuilder;
+import static com.mongodb.client.model.Filters.*;
public class DefaultFactory<K, T extends PersistentBase> extends
BaseFactory<K, T> {
@@ -45,8 +47,8 @@ public class DefaultFactory<K, T extends PersistentBase> extends
}
@Override
- public DBObject createFilter(final Filter<K, T> filter,
- final MongoStore<K, T> store) {
+ public Bson createFilter(final Filter<K, T> filter,
+ final MongoStore<K, T> store) {
if (filter instanceof FilterList) {
FilterList<K, T> filterList = (FilterList<K, T>) filter;
@@ -64,19 +66,17 @@ public class DefaultFactory<K, T extends PersistentBase> extends
}
}
- protected DBObject transformListFilter(final FilterList<K, T> filterList,
- final MongoStore<K, T> store) {
- BasicDBObject query = new BasicDBObject();
- for (Filter<K, T> filter : filterList.getFilters()) {
- boolean succeeded = getFilterUtil().setFilter(query, filter, store);
- if (!succeeded) {
- return null;
- }
- }
- return query;
+ protected Bson transformListFilter(final FilterList<K, T> filterList,
+ final MongoStore<K, T> store) {
+ List<Bson> filters = filterList.getFilters().stream()
+ .map(filter -> getFilterUtil().setFilter(filter, store))
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .collect(Collectors.toList());
+ return filters.isEmpty() ? new Document() : and(filters);
}
- protected DBObject transformFieldFilter(
+ protected Bson transformFieldFilter(
final SingleFieldValueFilter<K, T> fieldFilter,
final MongoStore<K, T> store) {
MongoMapping mapping = store.getMapping();
@@ -85,17 +85,16 @@ public class DefaultFactory<K, T extends PersistentBase> extends
FilterOp filterOp = fieldFilter.getFilterOp();
List<Object> operands = fieldFilter.getOperands();
- QueryBuilder builder = QueryBuilder.start(dbFieldName);
- builder = appendToBuilder(builder, filterOp, operands);
+ Bson filter = appendToBuilder(dbFieldName, filterOp, operands);
if (!fieldFilter.isFilterIfMissing()) {
// If false, the find query will pass if the column is not found.
- DBObject notExist = QueryBuilder.start(dbFieldName).exists(false).get();
- builder = QueryBuilder.start().or(notExist, builder.get());
+ Bson notExist = exists(dbFieldName, false);
+ filter = or(notExist, filter);
}
- return builder.get();
+ return filter;
}
- protected DBObject transformMapFilter(
+ protected Bson transformMapFilter(
final MapFieldValueFilter<K, T> mapFilter, final MongoStore<K, T> store) {
MongoMapping mapping = store.getMapping();
String dbFieldName = mapping.getDocumentField(mapFilter.getFieldName())
@@ -104,51 +103,43 @@ public class DefaultFactory<K, T extends PersistentBase> extends
FilterOp filterOp = mapFilter.getFilterOp();
List<Object> operands = mapFilter.getOperands();
- QueryBuilder builder = QueryBuilder.start(dbFieldName);
- builder = appendToBuilder(builder, filterOp, operands);
+ Bson filter = appendToBuilder(dbFieldName, filterOp, operands);
if (!mapFilter.isFilterIfMissing()) {
// If false, the find query will pass if the column is not found.
- DBObject notExist = QueryBuilder.start(dbFieldName).exists(false).get();
- builder = QueryBuilder.start().or(notExist, builder.get());
+ Bson notExist = exists(dbFieldName, false);
+ filter = or(notExist, filter);
}
- return builder.get();
+ return filter;
}
- protected QueryBuilder appendToBuilder(final QueryBuilder builder,
+ protected Bson appendToBuilder(final String dbFieldName,
final FilterOp filterOp, final List<Object> rawOperands) {
List<String> operands = convertOperandsToString(rawOperands);
switch (filterOp) {
case EQUALS:
if (operands.size() == 1) {
- builder.is(operands.iterator().next());
+ return eq(dbFieldName, operands.iterator().next());
} else {
- builder.in(operands);
+ return in(dbFieldName, operands);
}
- break;
case NOT_EQUALS:
if (operands.size() == 1) {
- builder.notEquals(operands.iterator().next());
+ return ne(dbFieldName, operands.iterator().next());
} else {
- builder.notIn(operands);
+ return nin(dbFieldName, operands);
}
- break;
case LESS:
- builder.lessThan(operands);
- break;
+ return lt(dbFieldName, operands);
case LESS_OR_EQUAL:
- builder.lessThanEquals(operands);
- break;
+ return lte(dbFieldName, operands);
case GREATER:
- builder.greaterThan(operands);
- break;
+ return gt(dbFieldName, operands);
case GREATER_OR_EQUAL:
- builder.greaterThanEquals(operands);
- break;
+ return gte(dbFieldName, operands);
default:
throw new IllegalArgumentException(filterOp
+ " no MongoDB equivalent yet");
}
- return builder;
}
/**
diff --git a/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/FilterFactory.java b/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/FilterFactory.java
index c68364f..5276852 100644
--- a/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/FilterFactory.java
+++ b/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/FilterFactory.java
@@ -17,13 +17,12 @@
*/
package org.apache.gora.mongodb.filters;
-import java.util.List;
-
import org.apache.gora.filter.Filter;
import org.apache.gora.mongodb.store.MongoStore;
import org.apache.gora.persistency.impl.PersistentBase;
+import org.bson.conversions.Bson;
-import com.mongodb.DBObject;
+import java.util.List;
/**
* Describe factory which create remote filter for MongoDB.
@@ -38,5 +37,5 @@ public interface FilterFactory<K, T extends PersistentBase> {
List<String> getSupportedFilters();
- DBObject createFilter(Filter<K, T> filter, MongoStore<K, T> store);
+ Bson createFilter(Filter<K, T> filter, MongoStore<K, T> store);
}
diff --git a/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/MongoFilterUtil.java b/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/MongoFilterUtil.java
index 8779af4..a7ccdc0 100644
--- a/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/MongoFilterUtil.java
+++ b/gora-mongodb/src/main/java/org/apache/gora/mongodb/filters/MongoFilterUtil.java
@@ -17,9 +17,6 @@
*/
package org.apache.gora.mongodb.filters;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.gora.filter.Filter;
@@ -28,8 +25,11 @@ import org.apache.gora.persistency.impl.PersistentBase;
import org.apache.gora.util.GoraException;
import org.apache.gora.util.ReflectionUtils;
import org.apache.hadoop.conf.Configuration;
+import org.bson.conversions.Bson;
-import com.mongodb.DBObject;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Optional;
/**
* Manage creation of filtering {@link org.apache.gora.query.Query} using
@@ -40,8 +40,7 @@ import com.mongodb.DBObject;
* </p>
*
* @author Damien Raude-Morvan draudemorvan@dictanova.com
- * @see #setFilter(com.mongodb.DBObject, org.apache.gora.filter.Filter,
- * org.apache.gora.mongodb.store.MongoStore)
+ * @see #setFilter(Filter, MongoStore)
*/
public class MongoFilterUtil<K, T extends PersistentBase> {
@@ -87,32 +86,29 @@ public class MongoFilterUtil<K, T extends PersistentBase> {
/**
* Set a filter on the <tt>query</tt>. It translates a Gora filter to a
* MongoDB filter.
- *
- * @param query
- * The Mongo Query
+ *
* @param filter
* The Gora filter.
* @param store
* The MongoStore.
* @return if remote filter is successfully applied.
*/
- public boolean setFilter(final DBObject query, final Filter<K, T> filter,
- final MongoStore<K, T> store) {
+ public Optional<Bson> setFilter(final Filter<K, T> filter,
+ final MongoStore<K, T> store) {
FilterFactory<K, T> factory = getFactory(filter);
if (factory == null) {
LOG.warn("MongoDB remote filter factory not yet implemented for "
+ filter.getClass().getCanonicalName());
- return false;
+ return Optional.empty();
} else {
- DBObject mongoFilter = factory.createFilter(filter, store);
+ Bson mongoFilter = factory.createFilter(filter, store);
if (mongoFilter == null) {
LOG.warn("MongoDB remote filter not yet implemented for "
+ filter.getClass().getCanonicalName());
- return false;
+ return Optional.empty();
} else {
- query.putAll(mongoFilter);
- return true;
+ return Optional.of(mongoFilter);
}
}
}
diff --git a/gora-mongodb/src/test/java/org/apache/gora/mongodb/filters/DefaultFactoryTest.java b/gora-mongodb/src/test/java/org/apache/gora/mongodb/filters/DefaultFactoryTest.java
index 3658e42..966f9be 100644
--- a/gora-mongodb/src/test/java/org/apache/gora/mongodb/filters/DefaultFactoryTest.java
+++ b/gora-mongodb/src/test/java/org/apache/gora/mongodb/filters/DefaultFactoryTest.java
@@ -17,8 +17,7 @@
*/
package org.apache.gora.mongodb.filters;
-import static org.junit.Assert.assertEquals;
-
+import com.mongodb.MongoClient;
import org.apache.avro.util.Utf8;
import org.apache.gora.examples.generated.WebPage;
import org.apache.gora.filter.FilterList;
@@ -27,11 +26,13 @@ import org.apache.gora.filter.MapFieldValueFilter;
import org.apache.gora.filter.SingleFieldValueFilter;
import org.apache.gora.mongodb.store.MongoStore;
import org.apache.hadoop.conf.Configuration;
+import org.bson.BsonDocument;
+import org.bson.conversions.Bson;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
-import com.mongodb.DBObject;
+import static org.junit.Assert.assertEquals;
public class DefaultFactoryTest {
@@ -56,9 +57,9 @@ public class DefaultFactoryTest {
filter.setFilterOp(FilterOp.NOT_EQUALS);
filter.setFilterIfMissing(true);
- DBObject dbObject = filterFactory.createFilter(filter, store);
+ Bson dbObject = filterFactory.createFilter(filter, store);
assertEquals(new JSONObject("{ \"url\" : { \"$ne\" : \"http://www.example.com\"}}").toString(),
- new JSONObject(dbObject.toString()).toString());
+ new JSONObject(asJson(dbObject)).toString());
}
@Test
@@ -67,9 +68,9 @@ public class DefaultFactoryTest {
filter.setFilterOp(FilterOp.EQUALS);
filter.setFilterIfMissing(false); // include doc with missing field
- DBObject dbObject = filterFactory.createFilter(filter, store);
+ Bson dbObject = filterFactory.createFilter(filter, store);
assertEquals(new JSONObject("{ \"$or\" : [ { \"url\" : { \"$exists\" : false}} , " +
- "{ \"url\" : \"http://www.example.com\"}]}").toString(), new JSONObject(dbObject.toString()).toString());
+ "{ \"url\" : \"http://www.example.com\"}]}").toString(), new JSONObject(asJson(dbObject)).toString());
}
@Test
@@ -78,9 +79,9 @@ public class DefaultFactoryTest {
filter.setFilterOp(FilterOp.NOT_EQUALS);
filter.setFilterIfMissing(true);
- DBObject dbObject = filterFactory.createFilter(filter, store);
+ Bson dbObject = filterFactory.createFilter(filter, store);
assertEquals(new JSONObject("{ \"h.C·T\" : { \"$ne\" : \"text/html\"}}").toString(),
- new JSONObject(dbObject.toString()).toString());
+ new JSONObject(asJson(dbObject)).toString());
}
@Test
@@ -89,17 +90,17 @@ public class DefaultFactoryTest {
filter.setFilterOp(FilterOp.EQUALS);
filter.setFilterIfMissing(false); // include doc with missing field
- DBObject dbObject = filterFactory.createFilter(filter, store);
+ Bson dbObject = filterFactory.createFilter(filter, store);
assertEquals(new JSONObject("{ \"$or\" : [ { \"h.C·T\" : { \"$exists\" : false}} , " +
- "{ \"h.C·T\" : \"text/html\"}]}").toString(), new JSONObject(dbObject.toString()).toString());
+ "{ \"h.C·T\" : \"text/html\"}]}").toString(), new JSONObject(asJson(dbObject)).toString());
}
@Test
public void testCreateFilter_list_empty() throws Exception {
FilterList<String, WebPage> filter = new FilterList<>();
- DBObject dbObject = filterFactory.createFilter(filter, store);
- assertEquals(new JSONObject("{ }").toString(), new JSONObject(dbObject.toString()).toString());
+ Bson dbObject = filterFactory.createFilter(filter, store);
+ assertEquals(new JSONObject("{ }").toString(), new JSONObject(asJson(dbObject)).toString());
}
@Test
@@ -114,9 +115,9 @@ public class DefaultFactoryTest {
urlFilter.setFilterOp(FilterOp.EQUALS);
filter.addFilter(urlFilter);
- DBObject dbObject = filterFactory.createFilter(filter, store);
+ Bson dbObject = filterFactory.createFilter(filter, store);
assertEquals(new JSONObject("{ \"h.C·T\" : \"text/html\" , \"url\" : \"http://www.example.com\"}").toString(),
- new JSONObject(dbObject.toString()).toString());
+ new JSONObject(asJson(dbObject)).toString());
}
/**
@@ -131,9 +132,9 @@ public class DefaultFactoryTest {
filter.getOperands().add(new Utf8("http://www.example.com"));
filter.setFilterIfMissing(true);
- DBObject dbObject = filterFactory.createFilter(filter, store);
+ Bson dbObject = filterFactory.createFilter(filter, store);
assertEquals(new JSONObject("{ \"url\" : \"http://www.example.com\"}").toString(),
- new JSONObject(dbObject.toString()).toString());
+ new JSONObject(asJson(dbObject)).toString());
}
private MapFieldValueFilter<String, WebPage> createHeadersFilter() {
@@ -150,4 +151,10 @@ public class DefaultFactoryTest {
filter.getOperands().add("http://www.example.com");
return filter;
}
+
+ private static String asJson(Bson bson) {
+ BsonDocument bsonDocument = bson.toBsonDocument(BsonDocument.class, MongoClient.getDefaultCodecRegistry());
+ return bsonDocument.toString();
+ }
+
}