Сохраните много записей, используя ReactiveMongo и Scala
Я пишу DAO Actor для MongoDB, который использует ReactiveMongo. Я хочу реализовать несколько очень простых операций CRUD, среди которых возможность сохранять множество записей за один раз. Поскольку у меня есть реактивное приложение (построенное на Akka), для меня важно иметь идемпотентные действия, поэтому мне нужно, чтобы операция была упертой, а не вставкой.
Пока у меня есть следующий (некрасивый) код для этого:
case class UpsertResult[T](nUpd: Int, nIns: Int, failed: List[T])
def upsertMany[T](l: List[T], collection: BSONCollection)
(implicit ec: ExecutionContext, w: BSONDocumentWriter[T]):
Future[UpsertResult[T]] = {
Future.sequence(l.map(o => collection.save(o).map(r => (o, r))))
.transform({
results =>
val failed: List[T] = results.filter(!_._2.ok).unzip._1
val nUpd = results.count(_._2.updatedExisting)
UpsertResult(nUpd, results.size - nUpd - failed.size, failed)
}, t => t)
}
Существует ли готовый способ одновременного добавления нескольких записей с использованием только API реагирующего монго?
Я новичок в MongoDB, поэтому многим это может показаться тривиальным. Любая помощь приветствуется!
2 ответа
Mongo не поддерживает загрузку нескольких документов в одном запросе. Например, операция обновления всегда может вставить только один новый элемент. Так что это не недостаток в драйвере реактивного монго, просто нет команды DB для достижения ожидаемого результата. Итерирование по документам, которые вы хотите сохранить, является правильным способом сделать это.
Руководство по mongodb о upsert содержит дополнительную информацию:
Согласно документам, BSSONCollection.save inserts the document, or updates it if it already exists in the collection
: смотри здесь. Теперь я не совсем уверен, как именно он принимает решение о том, существует ли документ или нет: предположительно, он основан на том, что ему сообщает MongoDB... так что это первичный ключ /id или уникальный индекс.
Короче говоря: я думаю, что вы делаете это правильно (в том числе ваш результат из LastError
).