如何查找具有重复数组元素的文档?

问题描述 投票:0回答:2

这是我的文件:

{ 
   "_id":"5b1ff7c53e3ac841302cfbc2",
   "idProf":"5b1ff7c53e3ac841302cfbbf",
   "pacientes":["5b20d2c83e3ac841302cfbdb","5b20d25f3e3ac841302cfbd0"]
}

我想知道如何使用Java中的MongoCollection在数组中找到重复的条目。

这就是我正在尝试的:

BasicDBObject query = new BasicDBObject("idProf", idProf);
query.append("$in", new BasicDBObject().append("pacientes", idJugador.toString()));

collection.find(query)
java mongodb mongodb-query
2个回答
0
投票

我们可以尝试在您的Java应用程序代码中解决这个问题。

private final MongoCollection collection;

public boolean hasDuplicatePacientes(String idProf) {
     Document d = collection.find(eq("idProf", idProf)).first();
     List<String> pacientes = (List<String>) d.get("pacientes");
     int original = pacientes.size();
     if (original == 0) {
         return false;
     }
     Set<String> unique = new HashSet(pacientes);
     return original != unique.size();
}

或者如果你正在寻找一种在db-side上完全做到这一点的方法,我相信它也可以提供像Neil Lunn这样的东西。


0
投票

最好的方法是将数组的长度与数组的长度进行比较,该数组将删除所有重复项。 “Set”没有重复的条目,因此您需要做的是将数组转换为“Set”并对原始文件进行测试。

现代MongoDB $expr

现代MongoDB版本有$expr,可以在常规查询中与聚合表达式一起使用。这里我们使用的表达式是$setDifference$size以及$ne用于布尔比较:

Document query = new Document(
  "$expr", new Document(
    "$ne", Arrays.asList(
      new Document("$size", "$pacientes"),
      new Document("$size",
        new Document("$setDifference", Arrays.asList("$pacientes", Collections.emptyList()))
      )
    )
  )
);

MongoCursor<Document> cursor = collection.find(query).iterator();

其序列化为:

{
  "$expr": {
    "$ne": [
      { "$size": "$pacientes" },
      { "$size": { "$setDifference": [ "$pacientes", [] ] } }
    ]
  }
}

这里实际上是$setDifference进行比较并返回唯一的元素。 $size返回原始文档数组内容和新减少的“集合”的长度。当然,如果这些“不相等”($ne),条件将是true,意味着在文件中发现了重复。

$expr操作时接收布尔值true/false值,以便是否将文档视为与条件匹配。

早期版本$where条款

基本上$where是一个在服务器上进行评估的JavaScript表达式

String whereClause = "this.pacientes.length != Object.keys(this.pacientes.reduce((o,e) => Object.assign(o, { [e.valueOf()]: null}), {})).length";

Document query = new Document("$where": whereClause);
MongoCursor<Document> cursor = collection.find(query).iterator();

您确实需要未在服务器上明确禁用JavaScript评估(这是默认设置),并且它不如使用$expr和本机聚合运算符那样高效。但是可以使用$where以相同的方式评估JavaScript表达式,Java代码中的参数基本上是作为字符串发送的。

在表达式中,.length是所有JavaScript数组的属性,因此您拥有原始文档内容以及与“set”的比较。 Array.reduce()使用每个数组元素作为结果对象中的“键”,然后Object.keys()将这些“键”作为新数组返回。

由于JavaScript对象的工作方式类似于Map,因此只允许使用唯一键,这是获得“设置”结果的一种方法。当然,当删除重复条目导致长度变化时,相同的!=比较将返回true。


$expr$where的任何一种情况下,这些是计算条件,其不能使用集合上存在的索引。因此,通常建议使用能够确实利用索引的使用规则相等或基于范围的query expressions的附加标准与这些表达式一起使用。谓词中的这些附加标准将在索引到位的情况下大大提高查询性能。

© www.soinside.com 2019 - 2024. All rights reserved.