这是我的文件:
{
"_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应用程序代码中解决这个问题。
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这样的东西。
最好的方法是将数组的长度与数组的长度进行比较,该数组将删除所有重复项。 “Set”没有重复的条目,因此您需要做的是将数组转换为“Set”并对原始文件进行测试。
$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的附加标准与这些表达式一起使用。谓词中的这些附加标准将在索引到位的情况下大大提高查询性能。