2016-08-05 2 views
0

Я пытаюсь сбрасывать базу данных mongo в объект json, но поскольку мои запросы к базе данных асинхронны, у меня возникают проблемы.Дамп базы данных ReactiveMongo с Play Framework 2.5

Каждая коллекция в моей базе данных содержит данные пользователя, и каждое имя коллекции является именем пользователя.

Итак, когда я хочу получить все данные моих пользователей, я восстанавливаю все имена коллекций, а затем перебираю их, чтобы каждый раз восстанавливать каждую коллекцию.

def databaseDump(prom : Promise[JsObject]) = { 
    for{ 
     dbUsers <- getUsers 
    } yield dbUsers 

var rebuiltJson = Json.obj() 
var array = JsArray() 
res.map{ users => 
    users.map{ userNames => 
    if(userNames.size == 0){ 
     prom failure new Throwable("Empty database") 
    } 
    var counter = 0 
    userNames.foreach { username => 
     getUserTables(username).map { tables => 
     /* Add data to array*/ 
      ... 
     counter += 1 
     if(counter == userNames.size){ 
      /*Add data to new json*/ 
      ... 
      prom success rebuiltJson 
     } 

     } 
    } 
    } 
} 

Это своего рода работает, но иногда обещание успешно срабатывает, даже если все данные еще не recoverd. Это связано с тем, что моя счетная переменная не является надежным решением.

Есть ли способ обойти всех пользователей, запросить базу данных и ждать, пока все данные будут восстановлены, прежде чем успешно выполнить обещание? Я пытался использовать это для понимания, но не нашел способ сделать это. Есть ли способ сбрасывать всю БД монго в один Json: { username : data, username : data ..}?

+0

Для такой задачи администрирования db я не думаю, что кодирование чего-то нового с использованием драйвера - это правильный путь. Утилита 'mongodump' может напрямую получать данные как JSON. Помимо этого, я бы предложил вам ознакомиться с документацией, чтобы понять, как [найти документ с помощью ReactiveMongo] (http://reactivemongo.org/releases/0.11/documentation/tutorial/find-documents.html) и что это [сериализация JSON] (http://reactivemongo.org/releases/0.11/documentation/json/overview.html) для. – cchantep

+0

Мне нужно сделать это в scala, потому что я пишу API. Таким образом, данные, которые я восстанавливаю, отправляются другим функциям, которые нужно обработать. Я использую сериализацию JSON, но я не вижу, как использовать его, чтобы сразу получить всю базу данных, а не коллекцию по коллекции. –

+0

«Демпинг» - это «всего лишь» конкретный случай нахождения (всего) документа некоторых документов (вариант использования, опять же, обычно обрабатывается специальными средствами администрирования db). – cchantep

ответ

0

Терминология пользователей/таблиц меня путала, поэтому я написал новую функцию, которая выгружает базу данных в один JsObject.

// helper function to find all documents inside a collection c 
// and return them as a single JsArray 
def getDocs(c: JSONCollection)(implicit ec: ExecutionContext) = c.find(Json.obj()).cursor[JsObject]().jsArray() 

def dumpToJsObject(db: DefaultDB)(implicit ec: ExecutionContext): Future[JsObject] = { 
    // get a list of all collections in the db 
    val collectionNames = db.collectionNames 
    val collections = collectionNames.map(_.map(db.collection[JSONCollection](_))) 

    // each entry is a tuple collectionName -> content (as JsArray) 
    val namesToDocs = collections.flatMap { 
    colls => Future.sequence(colls.map(c => getDocs(c).map(c.name -> _))) 
    } 

    // convert to a single JsObject 
    namesToDocs.map(JsObject(_)) 
} 

Я не проверял еще (я сделаю это позже), но эта функция должна по крайней мере дать вам общее представление. Вы получаете список всех коллекций внутри базы данных. Для каждой коллекции вы выполняете запрос, чтобы получить все документы внутри этой коллекции. Список документов преобразуется в JsArray, и, наконец, все коллекции состоят из одного JsObject с именами коллекций в виде ключей.

+0

Я пытаюсь реализовать это, но я получаю сообщение об ошибке с частью Future.sequence, NotInferedM [Future [NotInferedA]]. Я никогда не использовал функцию Future.sequence, поэтому я не знаю, что это значит. –

+0

Как уже было сказано, вы могли бы взглянуть на учебник или книгу о том, как работают [Scala Futures] (http://docs.scala-lang.org/overviews/core/futures.html) – cchantep

+0

@Carsten Я не мог получить ваш код работать, но я основывал свое решение. Функция Future.sequence - это то, что в конечном итоге решило мою проблему. Я создал List [Future [JsObject]] и использовал Future.sequence, чтобы преобразовать его в Future [List [JsObject]]. Затем я просто зациклился на нем. –

0

Если цель состоит в том, чтобы записать данные в выходной поток (локальный/файл или сеть), с побочными эффектами.

import scala.concurrent.{ ExecutionContext, Future } 
import reactivemongo.bson.BSONDocument 
import reactivemongo.api.{ Cursor, MongoDriver, MongoConnection } 

val mongoUri = "mongodb://localhost:27017/my_db" 

val driver = new MongoDriver 
val maxDocs = Int.MaxValue // max per collection 

// Requires to have an ExecutionContext in the scope 
// (e.g. `import scala.concurrent.ExecutionContext.Implicits.global`) 
def dump()(implicit ec: ExecutionContext): Future[Unit] = for { 
    uri <- Future.fromTry(MongoConnection.parseURI(mongoUri)) 
    con = driver.connection(uri) 
    dn <- Future(uri.db.get) 
    db <- con.database(dn) 
    cn <- db.collectionNames 
    _ <- Future.sequence(cn.map { collName => 
    println(s"Collection: $collName") 

    db.collection(collName).find(BSONDocument.empty). // findAll 
     cursor[BSONDocument]().foldWhile({}, maxDocs) { (_, doc) => 
     // Replace println by appropriate side-effect 
     Cursor.Cont(println(s"- ${BSONDocument pretty doc}")) 
     } 
    }) 
} yield() 

При использовании с сериализации пакета JSON, просто замените BSONDocument с JsObject (например BSONDocument.empty ~>Json.obj()).

Если вы тестируете Scala REPL, после вставки предыдущего кода его можно выполнить следующим образом.

dump().onComplete { 
    case result => 
    println(s"Dump result: $result") 
    //driver.close() 
} 
+0

Я положил Карстен в качестве решения, когда он ответил первым, и оба ваши ответы похожи –

Смежные вопросы