Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何从枚举器/迭代对象获取结果?_Scala_Playframework_Playframework 2.0_Reactivemongo - Fatal编程技术网

Scala 如何从枚举器/迭代对象获取结果?

Scala 如何从枚举器/迭代对象获取结果?,scala,playframework,playframework-2.0,reactivemongo,Scala,Playframework,Playframework 2.0,Reactivemongo,我正在使用play2和reactivemongo从mongodb获取结果。结果的每一项都需要转换以添加一些元数据。之后我需要对它进行排序 要处理转换步骤,我使用enumerate(): 然后我创建一个Iteratee,如下所示: val processIdeas: Iteratee[Idea, Unit] = Iteratee.foreach[Idea] { idea => resolveCrossLinks(idea) flatMap { idea => a

我正在使用play2和reactivemongo从mongodb获取结果。结果的每一项都需要转换以添加一些元数据。之后我需要对它进行排序

要处理转换步骤,我使用
enumerate()

然后我创建一个Iteratee,如下所示:

val processIdeas: Iteratee[Idea, Unit] =
  Iteratee.foreach[Idea] { idea =>
    resolveCrossLinks(idea) flatMap { idea =>
      addMetaInfo(idea.copy(history = None))
    }
  }
最后,我向迭代对象提供:

ideasEnumerator(processIdeas)
现在我被卡住了。我看到的每个示例都在
foreach
内部执行一些
println
,但似乎并不关心最终结果


因此,当所有文档都被返回并转换时,我如何获得序列、列表或其他我可以进一步处理的数据类型?

将迭代对象的签名从
Iteratee[Idea,Unit]
更改为
Iteratee[Idea,Seq[a]
,其中a是类型。基本上,Iteratee的第一个参数是输入类型,第二个参数是输出类型。在本例中,您将输出类型作为单位

看看下面的代码。它可能无法编译,但它提供了基本用法

ideasEnumerator.run(
  Iteratee.fold(List.empty[MyObject]) { (accumulator, next) => 
    accumulator + resolveCrossLinks(next) flatMap { next => 
      addMetaInfo(next.copy(history = None))
    } 
  }
) // returns Future[List[MyObject]]
如您所见,Iteratee只是一个状态机。只需提取Iteratee部分并将其分配给val:

val iteratee = Iteratee.fold(List.empty[MyObject]) { (accumulator, next) => 
        accumulator + resolveCrossLinks(next) flatMap { next => 
          addMetaInfo(next.copy(history = None))
        } 
      }

在我最后给出的答案的帮助下,您可以在任何需要从您的想法转换为列出[MyObject]的地方随意使用它

val processIdeas: Iteratee[Idea, Future[Vector[Idea]]] = 
    Iteratee.fold(Future(Vector.empty[Idea])) { (accumulator: Future[Vector[Idea]], next:Idea) =>
  resolveCrossLinks(next) flatMap { next =>
    addMetaInfo(next.copy(history = None))
  } flatMap (ideaWithMeta => accumulator map (acc => acc :+ ideaWithMeta))
}


val ideas = collection.find(query)
  .options(QueryOpts(page, perPage))
  .sort(Json.obj(sortField -> -1))
  .cursor[Idea]
  .enumerate(perPage).run(processIdeas)
这之后需要一个
ideas.flatMap(identity)
来消除未来的回归,但我认为这很好,一切看起来都很习惯和优雅


但是,与创建列表并随后对其进行迭代相比,所获得的性能可以忽略不计。

Iteratee.foreach
纯粹是以副作用为导向的(它实际上是大多数集合类型上的
foreach
惯例),并返回
Unit
。您需要的可能是一个
fold
的变体。如果您可以使用
列表
,您可以只使用
enum.run(Iteratee.getChunks)
。如果从迭代者抛出异常,它不会传播到枚举器,因此以后的recoverWith.map{}.recoverWith{}不起作用。我们如何解决这个问题?嘿@Anand!错误确实会传播。刚刚试过:)这里有一个要点:
val processIdeas: Iteratee[Idea, Future[Vector[Idea]]] = 
    Iteratee.fold(Future(Vector.empty[Idea])) { (accumulator: Future[Vector[Idea]], next:Idea) =>
  resolveCrossLinks(next) flatMap { next =>
    addMetaInfo(next.copy(history = None))
  } flatMap (ideaWithMeta => accumulator map (acc => acc :+ ideaWithMeta))
}


val ideas = collection.find(query)
  .options(QueryOpts(page, perPage))
  .sort(Json.obj(sortField -> -1))
  .cursor[Idea]
  .enumerate(perPage).run(processIdeas)