Scala и Casbah - ошибка: опция [com.mongodb.DBObject] не принимает параметры

Я пытаюсь получить документ и получить его атрибут. Когда я использую метод findOne, я ожидаю получить MongoDBObject, но я получаю Option[com.mongodb.DBObject]. Как из него получить атрибут? Можно ли вместо этого получить MongoDBObject?

scala> var col = MongoClient()("test")("counters")
col: com.mongodb.casbah.MongoCollection = MongoCollection({ "_id" : "some" , "value" : 0})

scala> var doc = col.findOne()
doc: Option[com.mongodb.DBObject] = Some({ "_id" : "some" , "value" : 0})

scala> doc("_id")
<console>:13: error: Option[com.mongodb.DBObject] does not take parameters
              doc("_id")
                 ^
scala>

3 ответа

Решение

Casbah API не знает содержимого вашей базы данных и не может быть уверен, что запрашиваемая вами запись действительно существует. В Java такой метод просто возвращает объект, который может быть null, Это не рекомендуется в Скала в пользу безопаснее Option[T] тип. Таким образом, вы вынуждены справиться с ситуацией, когда объект не существует. У вас есть несколько синтаксисов для этого (от худшего к лучшему:

Когда вы уверены, что объект есть - в противном случае будет выдано исключение

col.findOne().get

Когда вы хотите обработать оба случая:

col.findOne() match {
  case Some(r) => //r is your record
  case None => //record didn't exist
}

Когда вы хотите выполнить определенные операции с вашей записью (монадический стиль)

col.findOne().map(r => r("_id")).foreach(println)

Код выше напечатает _id столбец только если такая запись найдена - и ничего не делать иначе.

Вы получаете Option[DBObject] из-за вероятности того, что объект, который вы пытаетесь найти, может отсутствовать в базе данных.

Вы можете обработать это с match построить:

col.findOne() match{
  case Some(doc) => doc("id")
  case None => // not found
}

Вы получаете Option[DBObject]потому что, возможно, ничего не найдено, и в целом вы хотите избежать возврата null в scala (и любом другом функциональном языке). Есть несколько способов воздействовать на результат. Чтобы просто получить результат вы можете позвонить get, который выдаст исключение, если вы получите None из вашего запроса. Тогда есть getOrElse, который вы можете использовать для получения результата или значения по умолчанию, которое вы должны передать в вызов. И тогда есть orNull, который возвращает вам либо результат, либо ноль, если его нет. Вы также можете использовать foreach, если вы используете только результат для создания побочных эффектов, или map, если вы хотите получить определенное значение, а затем, например, вызвать getOrElse на полученный вариант.

Другие вопросы по тегам