2017-05-19 12 views
1
docs 참고

:

은 $ 일치하는 단계에 $ 텍스트를 사용하려면이는 $ 매치 무대의 첫 번째 단계되어야한다 파이프 라인.

몇 가지 예를 들어 JSON :

내가 고양이를 검색 할 경우 문제가
List<BasicDBObject> pipeline = new ArrayList<>() 
      BasicDBObject criteria = new BasicDBObject() 
      BasicDBObject theProjections = new BasicDBObject() 
      AggregateIterable iterable 

    //value is coming from a parameter 
     if (value != null) { 
    //a text index has been created on the title field 
      criteria.put('$text', new BasicDBObject('$search', value)) 

     } 
//cats is coming from a parameter but it will be an array of Strings 
if (cats.length != 0) { 

      ArrayList<BasicDBObject> orList = new ArrayList<>() 
      ArrayList<BasicDBObject> andList = new ArrayList<>() 
      BasicDBList theMegaArray = new BasicDBList() 


      for (int i = 1; i <= 5; i++) { 

       String identifier = "categories.category" + i 
       String cleanIdentifier = '$' + identifier 
       //If the category does not exist, put in a blank category 
       theMegaArray.add(new BasicDBObject('$ifNull', Arrays.asList(cleanIdentifier, Collections.EMPTY_LIST))) 
      } 
//merges all of the category arrays into 1 
      theProjections.put("allCategories", new BasicDBObject('$setUnion', theMegaArray)) 
      orList.add(new BasicDBObject("allCategories", new BasicDBObject('$all', cats))) 

      andList.add(new BasicDBObject('$or', orList)) 
      criteria.put('$and', andList) 
     } 
    pipeline.add(new BasicDBObject('$project', theProjections)) 
    pipeline.add(new BasicDBObject('$match', criteria)) 


    //and by default 
    iterable = collection.aggregate(pipeline) 

, 내가 먼저 파이프 라인에있을 투사를 필요 : 나는 다음과 같은 쿼리를

{"pid":"b00l16vp", "title": "in our time","categories":{"category1":["factual", "arts culture and the media", "history"]}} 
{"pid":"b0079mpp", "title": "doctor who", "categories":{"category2":["childrens", "entertainment and comedy", "animation"],"category1":["signed"]}} 
{“pid":"b00htbn3"} 
{“pid":"b00gdhqw","categories":{"category2":["factual"],"category3":["scotland"],"category4":["lifestyle and leisure", "food and drink"],"category1":["entertainment", "games and quizzes"]}} 

하지만 텍스트를 원한다면 먼저 일치하는 것이 필요합니다. 둘 다 할 수있는 방법이 있습니까?

+0

집계 파이프 라인의 맨 처음 단계 이외의 다른 것으로 "텍스트 검색"을 실행할 수 없습니다. 매우 간단한 이유는 인덱스가 필요하기 때문이며, 첫 번째 단계가 끝나면 문서의 구조가 변경되어 인덱스 사용이 무효화 될 수 있기 때문입니다. –

+0

거기에'$ setUnion'이 있습니다. 해당 배열의 모든 가능한 필드 이름에 텍스트 인덱스를 지정할 수 있음을 알고 있습니다. 성격에 의한 텍스트 검색은 모든 필드에서 작동하도록 지정하므로 병합 파이프 라인을 병합 할 필요가 없습니다. –

+0

cats 배열이 categories 객체에있는 것과 정확히 일치하도록하고 싶습니다. 나는 텍스트 검색이 오직 1 용어 @NeilLunn과 일치하는 경우에도 결과를 가져올 것이라고 믿는다. – kulsoompatel

답변

1

결국 아주 간단한 해결책입니다.

나는 새로운 기준이 아닌 원래의 기준이에

BasicDBObject criteriaCat = new BasicDBObject() 

추가를 범주 객체 생성.

criteriaCat.put('$and', andList) 

파이프 라인에서 $ match를 먼저 입력 한 다음 $ project를 입력하고 고양이가 있으면 결과에 다시 $ match를 실행합니다.

pipeline.add(new BasicDBObject('$match', criteria)) 
     pipeline.add(new BasicDBObject('$project', theProjections)) 

     if (cats.length != 0) { 
      pipeline.add(new BasicDBObject('$match', criteriaCat)) 
     } 
     pipeline.add(new BasicDBObject('$sort', sorting)) 

     //and by default 
     iterable = collection.aggregate(pipeline)