2017-05-19 21 views
1

$テキスト$検索が、必要$プロジェクトはdocsノートで:

$マッチ段階で$テキストを使用するには、$マッチステージは、第一段階である必要がありますパイプライン。

いくつかの例JSON:

{"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"]}} 

私は次のクエリを持っている:

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) 

問題は、私は猫を検索したい場合は、私が投影は第1パイプラインにする必要がありますしかし、もし私がテキストを望むなら、最初に一致する必要があります。私は両方を行うことができる方法はありますか?

+0

アグリゲーションパイプラインの最初のステージ以外のものとして「テキスト検索」を実行することはできません。非常に単純な理由は、索引が必要であり、最初の段階の後に文書の構造が変更され、索引の使用が無効になる可能性があるからです。 –

+0

そこに '$ setUnion'があります。あなたは、それらの配列の可能なすべてのフィールド名でテキストインデックスを指すことができます。自然界のテキスト検索は、指定するすべてのフィールドで機能します。したがって、集約パイプラインをマージする必要はありません。 –

+0

cats配列がcategoriesオブジェクトにあるものとまったく同じになるようにしたい。私はテキスト検索が1つの単語@NeilLunnにマッチしたとしても結果を出すと信じています – kulsoompatel

答えて

1

結局、これはかなり簡単な解決策です。私は新しい基準が

BasicDBObject criteriaCat = new BasicDBObject() 

オブジェクト作成

ではなく、元の基準のこのカテゴリを追加しました。

パイプラインに最初に$ matchを入れ、次に$ projectを追加し、catがある場合は結果に再び$一致を実行します。

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) 
関連する問題