从 MongoDB 中选择符合 K 个标准的数据

Selecting data from MongoDB where K of N criterias are met

我有包含四个字段的文档:A、B、C、D 现在我需要查找至少三个字段匹配的文档。例如:

查询:A=a,B=b,C=c,D=d

返回的文件:

  1. a,b,c,d (four of four met)
  2. a,b,c (three of four met)
  3. a,b,d (another three of four met)
  4. a,c,d (another three of four met)
  5. b,c,d (another three of four met)

到目前为止,我创建了如下内容:

`(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 数据,但我认为这无关紧要。我当前的代码:

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

目前在 MongoDB 中我们无法直接执行此操作,因为我们没有任何功能支持 Permutation/Combination 查询参数。

但我们可以通过将条件分解成多个部分来简化查询。

使用Aggregation管道

$project with records (A=a AND B=b) --> This will give the records which are having two conditions matching.(我们的 objective 是在给定条件下查找匹配 4 中的 3 或 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.

希望对您有所帮助!

按照您的方式,您必须在查询中进行所有排列。您可以使用聚合框架来执行此操作而无需排列所有组合。而且它足够通用,可以处理任何 K。缺点是我认为你需要 Mongodb 3.2+ 并且 Spring 数据还不支持这些操作:$filter $concatArrays

但是您可以使用 java 驱动程序轻松完成。

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

您所做的只是将需要检查的所有字段的值连接到一个数组中。然后 select 这些元素的子集等于您要查找的值(或您想要的任何条件),最后获得每个文档的数组大小。

现在您需要做的就是$match大小大于或等于您想要的文档。