【问题标题】:MongoDB Scala Driver Pushing to a nested ArrayMongoDB Scala 驱动程序推送到嵌套数组
【发布时间】:2018-08-13 02:45:40
【问题描述】:

我在使用 Scala 中的 Mongo 正确附加到嵌套数组时遇到了一些麻烦。我在 Node.js 中多次执行相同的操作,但由于某种原因,我无法将其转换为 Scala。

这是主要的“模式”:

case class Band(
             _id: ObjectId,
             name: String,
             username: String,
             email: String,
             path: String,
             tours: List[Tour],
             merchSets: List[MerchSet],
             facebook: Option[String],
             twitter: Option[String],
             youtube: Option[String],
             instagram: Option[String],
             website: Option[String]
           )

object Band {

  def apply(
         _id: ObjectId,
         name: String,
         username: String,
         email: String,
         path: String,
         tours: List[Tour],
         merchSets: List[MerchSet],
         facebook: Option[String],
         twitter: Option[String],
         youtube: Option[String],
         instagram: Option[String],
         website: Option[String]
       ): Band = new Band(_id,
    name, username, email, path, tours, merchSets, facebook, twitter, 
youtube, instagram, website)

  val bandCodecRegistry: CodecRegistry = 
 fromRegistries(fromProviders(classOf[Band]), DEFAULT_CODEC_REGISTRY)
}

如您所见,此定义有一个 旅游列表,其中 旅游 定义为:

case class Tour(_id: ObjectId,
            name: String,
            shows: List[Show],
            items: List[Item],
            region: String,
            default_merchset : Option[MerchSet]
           )

 object Tour{
   def apply(_id: ObjectId,
        name: String,
        shows: List[Show],
        items: List[Item],
        region: String,
        default_merchset: Option[MerchSet]
       ): Tour = new Tour(_id, name, shows, items, region, default_merchset)

  val tourCodecRegistry : CodecRegistry = 
      fromRegistries(fromProviders(classOf[Tour]), DEFAULT_CODEC_REGISTRY)
}

我正在尝试将一个项目推送到项目集合中,如果它不存在,那么每当创建一个新项目时。

基本上,端点接收一个乐队id、一个旅游名称和一组用于创建和推送项目的表单参数。

GOAL:查询需要从对应的tours集合中找到正确的band和正确的tour,并将创建的item添加到对应的tour.items中

我在 Node.js 中执行此操作的方式如下:

var query = {"_id": id, "tours.name": name}
Band.findOneAndUpdate(
    query,
    {$push: {"tours.$.items": item}}
  )

但这在 Scala 中是行不通的。而且我完全没有错误。尽管数据库中没有任何变化,但订阅达到了 OnComplete 案例。 OnNext 案例不会受到打击。不知何故,查询完成没有错误,也没有成功......

这是我目前拥有的:

val add = MongoDataBaseConnector.bands.findOneAndUpdate(and(equal("_id", id),
  equal("tours.name", tour_name)),
  push("tours.items", request.toDomain))

我尝试在中间使用 $ 运算符并使用 addToSet 但它们没有任何区别。

解决这个问题的正确方法是什么?

注意:这是官方的 scala 驱动,不是 casbah。如何在 casbah 中做到这一点已被多次回答。

【问题讨论】:

  • 你能把上述案例类的伴生对象的代码贴出来吗?
  • @zenwraight 完成。它仅适用并且它们存储编解码器但仍然...
  • 我觉得你需要导入 play.api.libs.json._ 然后有一行像 - 隐式 val format: Format[Band] = Json.format[Band] ,所以这基本上得到一个 json.obj 超出您的案例类对象,然后尝试将其推送到 mongodb 。我一般都是这样的。
  • @zenwraight 感谢您的建议。我正在使用 finatra,并且一直在努力避免参与其中。我实际上已经缩小了问题的范围,并意识到查询本身不起作用。我会尽快用我的发现更新问题
  • @zenwraight 原来我忘记将 id 转换为 ObjectId() ....

标签: mongodb scala


【解决方案1】:

原来我忘记将 id 转换为 ObjectId ... 下面的查询有效

def addTourSpecificMerch(request: NewItemRequest, id: ObjectId, name: String): Unit = {
    val tour_name = name.replace("%20", " ")
    val add = MongoDataBaseConnector.bands.findOneAndUpdate(and(equal("_id", id),
      equal("tours.name", tour_name)),
      addToSet("tours.$.items", request.toDomain))

    add.subscribe(new Observer[Band] {
      override def onNext(result: Band): Unit = println(s"onNext: $result")
      override def onError(e: Throwable): Unit = println(s"onError: $e")
      override def onComplete(): Unit = println("onComplete")
    })
}

【讨论】:

  • 很好,我想你可以接受你自己的帖子作为未来面临类似问题的人的答案。
  • @zenwraight 是的,但有时间限制。 24小时后我可以接受:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-28
  • 1970-01-01
  • 2017-05-09
相关资源
最近更新 更多