2016-09-26 78 views
3

我有四個字段的文檔:A,B,C,D現在我需要找到至少有三個字段匹配的文檔。例如:從MongoDB中選擇滿足N個條件的K個數據

查詢:A = A,B = B,C = C,d = d

返回的文檔:

  1. A,B,C,d(4四滿足)
  2. A,b,C(三四滿足)
  3. 的a,b,d(另外三個四個滿足)
  4. A,C,d(另外三個四個滿足)
  5. B,C,d(另外三四個滿足)

到目前爲止,我創建了類似:

`(A=a AND B=b AND C=c) 
OR (A=a AND B=b AND D=d) 
OR (A=a AND C=c AND D=d) 
OR (B=b AND C=c AND D=d)` 

但是,這是醜陋的,而且容易出錯。

有沒有更好的方法來實現它?另外,查詢性能也很重要。

我正在使用Spring Data,但我認爲沒關係。我當前的代碼:

Criteria c = new Criteria(); 

    Criteria ca = Criteria.where("A").is(doc.getA()); 
    Criteria cb = Criteria.where("B").is(doc.getB()); 
    Criteria cc = Criteria.where("C").is(doc.getC()); 
    Criteria cd = Criteria.where("D").is(doc.getD()); 

    c.orOperator(
      new Criteria().andOperator(ca,cb,cc), 
      new Criteria().andOperator(ca,cb,cd), 
      new Criteria().andOperator(ca,cc,cd), 
      new Criteria().andOperator(cb,cc,cd) 
    ); 
    Query query = new Query(c); 

    return operations.find(query, Document.class, "documents"); 

回答

1

你有它的方式你必須做你的查詢所有排列。您可以使用聚合框架來完成此操作,而無需置換所有組合。它的通用性足以滿足K。缺點是我認爲你需要Mongodb 3.2+,而且Spring Data還不支持這些運算:$filter$concatArrays

但是你可以用java驅動來做到這一點。

[ 
    { 
     $project:{ 
     totalMatched:{ 
      $size:{ 
       $filter:{ 
        input:{ 
        $concatArrays:[ ["$A"], ["$B"], ["$C"],["$D"]] 
        }, 
        as:"attr", 
        cond:{ 
        $eq:["$$attr","a"] 
        } 
       } 
      } 
     } 
     } 
    }, 
    { 
     $match:{ 
     totalMatched:{ $gte:3 } 
     } 
    } 
] 

您所做的只是將所有需要檢查的字段的值連接在一個數組中。然後選擇這些元素的一個子集,這些元素等於您正在查找的值(或您想要的任何條件),並最終爲每個文檔獲取該數組的大小。

現在您只需要$match大小大於或等於您想要的文件。

2

目前在MongoDB中,我們不能直接這樣做,因爲我們沒有在查詢參數支持置換/組合的任何功能。

但是我們可以通過將條件分解成多個部分來簡化查詢。

使用Aggregation管道

$projectwith records (A=a AND B=b) --> This will give the records which are having two conditions matching.(我們的目標是找到其在給定的條件有3場比賽開出4或4開出4的記錄)`

Next in the pipeline use OR condition (C=c OR D=d) to find the final set of records which yields our expected result. 

希望它幫助!

相關問題