Сложный и-или запрос в морфии
Я пытался объединить методы и() и или() интерфейса запроса, чтобы создать набор условий, где есть 2 списка критериев, и по крайней мере один из каждого должен быть удовлетворен.
Я прочитал это обсуждение и пытался использовать запрос.и () объединить мои два пункта $or.
По существу, я пытаюсь сказать:
Criteria[] arrayA;
Criteria[] arrayB;
// Programatically populate both arrays
Query q = dao.createQuery().and(
q.or(arrayA),
q.or(arrayB)
);
Я использую массивы критериев, потому что мне приходится перебирать несколько различных входных данных для генерации конкретного мне нужны критерии, и этот подход работает, когда я просто использую один $or, но я не могу заставить Morphia генерировать запрос, который я ожидаю, когда я пытаюсь включить оба предложения $or в $and, как я объяснил выше. Я обнаруживаю, что нет запроса $and, а второй $or перезаписал первый, как если бы я просто вызвал or() дважды.
Например, я ожидаю, что запрос будет сгенерирован следующим образом:
{
"$and": {
"0": {
"$or": {
"0": //Some criteria,
"1": //Some criteria,
"2": //Some criteria,
}
},
"1": {
"$or": {
"0": //Some other criteria,
"1": //Some other criteria,
"2": //Some other criteria,
}
}
}
Однако я просто получаю такой запрос:
{
"$or": {
"0": //Some other criteria,
"1": //Some other criteria,
"2": //Some other criteria,
}
}
Я не вижу много документации, но глядя на тестовый случай,кажется, что это правильный путь. Может ли кто-нибудь помочь пролить свет на то, почему это не работает, как я ожидаю?
(Этот вопрос был перекрестно отправлен в список рассылки Morphia , поскольку я не уверен, какое место получит лучший ответ)
Править 0:
Обновление: возвращаясь к этому, я проверил тестовый код морфия, и все работает нормально, я не смог воспроизвести свою проблему в тесте код.
Поэтому я создал новый проект, чтобы попытаться получить рабочий пример запроса, который я хочу. Однако я столкнулся с той же проблемой, даже с тестовым проектом barebones.Проект является mavenised, и POM является:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Test</name>
<dependencies>
<dependency>
<groupId>com.google.code.morphia</groupId>
<artifactId>morphia</artifactId>
<version>0.99</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- Force the use of the latest java mongoDB driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.7.3</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
У меня есть тестовый класс:
import java.util.Map;
import com.google.code.morphia.annotations.Entity;
@Entity
public class TestEntity {
Map<String, Integer> map;
}
И, наконец, мой тестовый класс:
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import com.google.code.morphia.Datastore;
import com.google.code.morphia.Morphia;
import com.google.code.morphia.query.Query;
import com.google.code.morphia.query.QueryImpl;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
public class Test {
static Mongo mongo;
static Morphia m;
static Datastore ds;
static {
mongo = null;
try {
mongo = new Mongo();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (MongoException e) {
e.printStackTrace();
}
m = new Morphia();
ds = m.createDatastore(mongo, "test");
}
public static void main(String[] args) {
populate();
query();
}
public static void query() {
Query<TestEntity> q = ds.createQuery(TestEntity.class);
q.and(q.or(q.criteria("map.field1").exists()),
q.or(q.criteria("map.field2").exists()));
Iterable<TestEntity> i = q.fetch();
for (TestEntity e : i) {
System.out.println("Result= " + e.map);
}
QueryImpl<TestEntity> qi = (QueryImpl<TestEntity>) q;
System.out
.println("Query= " + qi.prepareCursor().getQuery().toString());
}
public static void populate() {
TestEntity e = new TestEntity();
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("field1", 1);
map.put("field2", 2);
e.map = map;
ds.save(e);
}
}
Для меня приведенный выше код не производит правильный запрос $and, но я не могу понять, почему
2 ответа:
Просто догадываюсь (не успеваю проверить), но Должно ли это быть:
Query q = dao.createQuery().and( q.or(q.criteria(arrayA)), q.or(q.criteria(arrayB)) );
Обновление Вы правы,
Query.criteria
не было правильным-это было то, что использовалось в простом тесте, поэтому я подумал, что вы что-то пропустили. Это, кажется, работает для меня (разбивая его на два утверждения):Query q = dao.createQuery(); q.and( q.or(arrayA), q.or(arrayB) );
Обновление 2 Более полный тестовый код:
Criteria[] arrayA = {dao.createQuery().criteria("test").equal(1), dao.createQuery().criteria("test").equal(3)}; Criteria[] arrayB = {dao.createQuery().criteria("test").equal(2), dao.createQuery().criteria("test").equal(4)};; Query q = dao.createQuery(); q.and( q.or(arrayA), q.or(arrayB) ); System.out.println(q.toString());
Дает:
{ "$and" : [ { "$or" : [ { "test" : 1} , { "test" : 3}]} , { "$or" : [ { "test" : 2} , { "test" : 4}]}]}
Несмотря на морфий 0.99, включая метод
Query.and(Criteria ...)
, он не генерирует правильный запрос.Выпуск 338 , в котором рассматривается поддержка явных $и предложений в запросах, нацелен на Morphia 0.99.1, которая в настоящее время доступна только в виде версии моментального снимка через Maven.
Однако использование 0.99.1-SNAPSHOT решило эту проблему для нас.