如果我想使用Scala删除MongoDB集合中的重复文档,那么如何去做呢?
很确定它很简单,但我总是在Mongo Shell中找到方法。
在这个例子中,我使用版本2.1.0 for Scala 2.11。
我想您要删除除了_id字段之外重复相同属性的所有文档。
我在用户集合中有四个文档。
{
"_id": <ObjectId>,
"name": "John",
"surname": "Doe"
}
{
"_id": <ObjectId>,
"name": "John",
"surname": "Doe"
}
{
"_id": <ObjectId>,
"name": "John",
"surname": "Doe"
}
{
"_id": <ObjectId>,
"name": "Dione",
"surname": "Elton"
}
在这个例子中,我们将删除name = John和surname = Doe的三个文档中的两个,保留这些文档:
{
"_id": <ObjectId>,
"name": "John",
"surname": "Doe"
}
{
"_id": <ObjectId>,
"name": "Dione",
"surname": "Elton"
}
我已经使用过此代码,它适用于此示例:
val client = MongoClient("mongodb://localhost:27017")
val database = client.getDatabase("test")
val collection = database.getCollection("users")
val future = collection.find().toFuture()
val allDocs = Await.result(future, Duration.Inf)
allDocs
.map { d => (d.filterKeys { x => !x.equals("_id")}, d.get("_id").get ) }
.groupBy(_._1)
.map(_._2.map(_._2))
.filter(_.size > 1)
.map({ids => ids.take(ids.size - 1)})
.flatten
.foreach{
id => collection.deleteOne(equal("_id", id)).subscribe(
(dr: DeleteResult) => println(dr.getDeletedCount),
(e: Throwable) => println(s"Error when deleting the document $id: $e")
)
}
三个第一行非常简单,我们连接到我们的数据库并获取集合对象。然后,我们从集合中检索所有文档。请注意,MongoDB Scala驱动程序是异步的,所以我采用了未来的对象以等待结果,因为我需要它们继续。
现在是棘手的部分。我将逐行解释。首先,我们将每个文档映射到一个元组,其中第一个元素是没有_id字段的文档,第二个元素是_id。
.map { d => (d.filterKeys { x => !x.equals("_id")}, d.get("_id").get ) }
一旦我们有了元组,我们就可以按照没有_id字段的文档对序列进行分组。它将生成一个映射,其中键是没有_id字段的文档,值是元组序列,它们表示每个对(没有_id,_id的文档),其内容与键相同。
.groupBy(_._1)
由于我们对_ids感兴趣,我们需要获取每个Map对象的值,并且对于值序列的每个元素,都需要_id。
.map(_._2.map(_._2))
现在我们有一系列序列。每个序列都包含没有_id的每个唯一文档的_ids。下一步是过滤序列,以便我们只有那些大小大于1的序列。换句话说,我们正在过滤表示重复文档的_ids。
.filter(_.size > 1)
Le取每个序列的n-1个第一个_id。它们将是要删除的重复文档。
.map({ids => ids.take(ids.size - 1)})
让我们展平序列的顺序,这样我们就有了一系列_ids。
.flatten
最后,我们可以从我们的集合中删除每个_id。我是通过使用foreach方法完成的,并逐个删除文档。由于我们使用的是subscribe方法,因此将异步删除文档。
.foreach{
id => collection.deleteOne(equal("_id", id)).subscribe(
(dr: DeleteResult) => println(dr.getDeletedCount),
(e: Throwable) => println(s"Error when deleting the document $id: $e")
)
}
希望能帮助到你!