2012-04-23 2 views
7

나는 쿼리 인터페이스의 and() 및 or() 메소드를 결합하여 조건 목록을 두 개 이상 만들고 각 조건의 목록을 하나씩 만들려고했습니다. 반드시 만족해야합니다.Morphia에서 복잡한 AND-OR 쿼리

나는 this discussion을 읽고 내 두 개의 $ 또는 절을 결합하기 위해 Query.and()를 사용하려고했습니다.

기본적으로 내가 말하려고 해요 :

Criteria[] arrayA; 
Criteria[] arrayB; 

// Programatically populate both arrays 

Query q = dao.createQuery().and(
    q.or(arrayA), 
    q.or(arrayB) 
); 

을 내가 루프가 있기 때문에 내가 필요로하는 특정 기준을 생성하기 위해 여러 가지 입력을 통해 기준의 배열을 사용하고 있는데,이 방법은 때를 작동 I 단 하나의 $ 또는를 사용하고 있습니다. 그러나 Morphia가 $와 절을 모두 포함하려고 시도 할 때 기대하는 쿼리를 생성 할 수 없습니다. 나는 $ 나 질의가없고 두 번째 $는 처음에 겹쳐 쓰거나 그냥 두 번이나()를 두 번 호출 한 것처럼 보였다.

{ 
    "$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, 
    } 
} 

것은 내가 많은 문서를 볼 수 있지만,보고

예 : 나는 쿼리는 다음과 같이 생성 될 것으로 예상 테스트 케이스, 이것은 이것에 대해 갈 수있는 올바른 방법 인 것 같습니다. 누구나 내가 예상 한대로 작동하지 않는 이유를 밝힐 수 있습니까?

편집 0 (이 질문은 내가 최고의 응답을 얻을 것이다 장소 모르겠어요으로, cross-posted to the Morphia mailing list했다) :

업데이트 :이 재 방문, 나는 모르핀 테스트 코드를 체크 아웃 한 그리고 모든 것이 잘 실행되기 때문에 테스트 코드에서 내 문제를 재현 할 수 없었습니다.

따라서 필자는 필자가 원하는 쿼리의 실습 예제를 만들기 위해 새로운 프로젝트를 만들었습니다. 그러나 barebones 테스트 프로젝트에서도 동일한 문제가 발생했습니다. 나를 위해

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); 
    } 
} 

:

이 프로젝트는 mavenised되고, POM은 다음과 같습니다

import java.util.Map; 

import com.google.code.morphia.annotations.Entity; 

@Entity 
public class TestEntity { 
    Map<String, Integer> map; 
} 

그리고 마지막으로 내 테스트 클래스 : 나는 TestEntity 클래스가

<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> 

위의 코드는 올바른 $ 및 쿼리를 생성하지 않지만 이유를 볼 수 없습니다.

,210

답변

6

포함 모르핀 0.99에도 불구하고이 (두 문장으로 위반) 나를 위해 작동하는 것 같다 Query.and(Criteria ...) 메서드는 올바른 쿼리를 생성하지 않습니다. 명시 적 $ 쿼리에 조항에 대한 지원을 해결

Issue 338은 메이븐을 통해 스냅 샷 버전으로 현재에서만 사용할 수 있습니다 모르핀 0.99.1, 대상으로합니다.

그러나 0.99.1-SNAPSHOT을 사용하면 문제가 해결되었습니다.

+1

에 대한 문제가 해결되어 최종 작업 예제가 제공됩니다. –

+0

안녕하세요 @RussBateman, 코드가 변경되지 않았습니다. 버전 0.99에 0.99.1-SNAPSHOT에서 해결 된 문제가있는 것 같습니다. 그래서 우리는 단순히 우리가 사용하고있는 라이브러리의 버전을 변경했습니다 (이상적은 아니지만 – chrisbunney

+0

0.99.1-SNAPSHOT을 사용해도 Query.and()에 여전히 문제가 있습니다. 기준이 단순한 필드라면 괜찮습니다. $ 또는 criterial이 $에 포함되어 있으면 실패합니다. –

7

단지 (테스트 할 시간이 없어) 추측하지만, 그것이 있어야 : 네 말이 맞아

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

'Query.criteria()'는 문자열 (필드 이름 임) 만 사용하기 때문에 두 배열은 모두'Criteria' 객체의 목록입니다. 사용할 대체 방법은 없으며, 단일 또는 절을 구성하기 위해 배열을 전달한 이후로 Morphia 코드를 체크하고이 시나리오에 대한 테스트 케이스를 작성해야 할 수도 있습니다. – chrisbunney

+0

더 나은 대답으로 업데이트되었습니다. 희망이 당신을 위해 작동합니다. –

+0

업데이트 해 주셔서 감사합니다. 흥미 롭습니다. 내 실제 쿼리는 내 의도를 설명하기 위해 준 예제보다는 더 복잡하지만 원리는 건전하다고 생각했습니다. 아마도 문제는 쿼리 코드의 다른 곳에서 발생하며 이것은 단지 증상 일뿐입니다 ... – chrisbunney