Browse Source

DATAMONGO-429 - Fixed handling of nested arrays in QueryMapper.

QueryMapper now correctly transforms arrays not concreting them into BasicDBObjects anymore.
1.0.x
Oliver Gierke 14 years ago
parent
commit
cb6a1b7110
  1. 43
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryMapper.java
  2. 16
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryMapperUnitTests.java

43
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/QueryMapper.java

@ -30,6 +30,7 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject; import com.mongodb.BasicDBObject;
import com.mongodb.DBObject; import com.mongodb.DBObject;
@ -41,6 +42,9 @@ import com.mongodb.DBObject;
*/ */
public class QueryMapper { public class QueryMapper {
private static final List<String> DEFAULT_ID_NAMES = Arrays.asList("id", "_id");
private static final String N_OR_PATTERN = "\\$.*or";
private final ConversionService conversionService; private final ConversionService conversionService;
private final MongoConverter converter; private final MongoConverter converter;
@ -59,8 +63,8 @@ public class QueryMapper {
* Replaces the property keys used in the given {@link DBObject} with the appropriate keys by using the * Replaces the property keys used in the given {@link DBObject} with the appropriate keys by using the
* {@link PersistentEntity} metadata. * {@link PersistentEntity} metadata.
* *
* @param query * @param query must not be {@literal null}.
* @param entity * @param entity can be {@literal null}.
* @return * @return
*/ */
public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity) { public DBObject getMappedObject(DBObject query, MongoPersistentEntity<?> entity) {
@ -68,8 +72,10 @@ public class QueryMapper {
DBObject newDbo = new BasicDBObject(); DBObject newDbo = new BasicDBObject();
for (String key : query.keySet()) { for (String key : query.keySet()) {
String newKey = key; String newKey = key;
Object value = query.get(key); Object value = query.get(key);
if (isIdKey(key, entity)) { if (isIdKey(key, entity)) {
if (value instanceof DBObject) { if (value instanceof DBObject) {
DBObject valueDbo = (DBObject) value; DBObject valueDbo = (DBObject) value;
@ -81,34 +87,51 @@ public class QueryMapper {
} }
valueDbo.put(inKey, ids.toArray(new Object[ids.size()])); valueDbo.put(inKey, ids.toArray(new Object[ids.size()]));
} else { } else {
value = getMappedObject((DBObject) value, entity); value = getMappedObject((DBObject) value, null);
} }
} else { } else {
value = convertId(value); value = convertId(value);
} }
newKey = "_id"; newKey = "_id";
} else if (key.startsWith("$") && key.endsWith("or")) { } else if (key.matches(N_OR_PATTERN)) {
// $or/$nor // $or/$nor
Iterable<?> conditions = (Iterable<?>) value; Iterable<?> conditions = (Iterable<?>) value;
BasicBSONList newConditions = new BasicBSONList(); BasicBSONList newConditions = new BasicBSONList();
Iterator<?> iter = conditions.iterator(); Iterator<?> iter = conditions.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
newConditions.add(getMappedObject((DBObject) iter.next(), entity)); newConditions.add(getMappedObject((DBObject) iter.next(), null));
} }
value = newConditions; value = newConditions;
} else if (key.equals("$ne")) { } else if (key.equals("$ne")) {
value = convertId(value); value = convertId(value);
} else if (value instanceof DBObject) {
newDbo.put(newKey, getMappedObject((DBObject) value, entity));
continue;
} }
newDbo.put(newKey, converter.convertToMongoType(value)); newDbo.put(newKey, convertSimpleOrDBObject(value, null));
} }
return newDbo; return newDbo;
} }
/**
* Retriggers mapping if the given source is a {@link DBObject} or simply invokes the
*
* @param source
* @param entity
* @return
*/
private Object convertSimpleOrDBObject(Object source, MongoPersistentEntity<?> entity) {
if (source instanceof BasicDBList) {
return converter.convertToMongoType(source);
}
if (source instanceof DBObject) {
return getMappedObject((DBObject) source, entity);
}
return converter.convertToMongoType(source);
}
/** /**
* Returns whether the given key will be considered an id key. * Returns whether the given key will be considered an id key.
* *
@ -123,7 +146,7 @@ public class QueryMapper {
return idProperty.getName().equals(key) || idProperty.getFieldName().equals(key); return idProperty.getName().equals(key) || idProperty.getFieldName().equals(key);
} }
return Arrays.asList("id", "_id").contains(key); return DEFAULT_ID_NAMES.contains(key);
} }
/** /**

16
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/QueryMapperUnitTests.java

@ -1,11 +1,11 @@
/* /*
* Copyright (c) 2011 by the original author(s). * Copyright 2011-2012 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -186,6 +186,18 @@ public class QueryMapperUnitTests {
assertThat(result.get("bar"), is(notNullValue())); assertThat(result.get("bar"), is(notNullValue()));
} }
/**
* @see DATAMONGO-429
*/
@Test
public void transformsArraysCorrectly() {
Query query = new BasicQuery("{ 'tags' : { '$all' : [ 'green', 'orange']}}");
DBObject result = mapper.getMappedObject(query.getQueryObject(), null);
assertThat(result, is(query.getQueryObject()));
}
class Sample { class Sample {
@Id @Id

Loading…
Cancel
Save