如何在现有scala枚举器中有条件地添加新枚举器

如何在现有scala枚举器中有条件地添加新枚举器,scala,playframework,enumerator,iterate,Scala,Playframework,Enumerator,Iterate,我的堆栈是:Scala 2.11.6,ReactiveMongo 0.11.6,Play 2.4.2,Mongo 3.0.4 我有一个到mongo的查询列表,我需要有条件地一个接一个地执行这些查询(如果结果数小于最大可能值) 作为一个解决方案,我正在做以下工作: possibleQueries. // find returns Enumerator[JsObject] map(query => searchableCollection.find(query)). /

我的堆栈是:Scala 2.11.6,ReactiveMongo 0.11.6,Play 2.4.2,Mongo 3.0.4

我有一个到mongo的查询列表,我需要有条件地一个接一个地执行这些查询(如果结果数小于最大可能值)

作为一个解决方案,我正在做以下工作:

possibleQueries.
    // find returns Enumerator[JsObject]
    map(query => searchableCollection.find(query)).
    // combine Enumerators with andThen
    foldLeft(Enumerator.empty[JsObject])({ (e1, e2) => e1.andThen(e2) }) through 
    // Take only specified amount of suggestions
    take[JsObject](MAX_AMOUNT)
  • 将查询与组合,然后组合
  • 使用Enumerate.take[Int](n)限制结果数
  • 问题是,它急切地使用searchableCollection.find(query)搜索数据(可能我错了),如果以前的查询返回最大数量的结果,它甚至可能无法获取返回的结果

    如何重写它,以便仅当前面的枚举未填充最大数量的响应时才调用搜索

    更新

    我采用的解决方案是

    implicit class EnumeratorExtension[E](parent: Enumerator[E]) {
    
      /**
       * Create an Enumeratee that combines parent & e if parent was empty.
       */
      def andIfEmpty(e: => Enumerator[E]): Enumerator[E] = new Enumerator[E] {
        def apply[A](i: Iteratee[E, A]): Future[Iteratee[E, A]] = {
          var empty = true
          parent.
            map(e => {
              empty = false
              e
            })(defaultExecutionContext).
            apply(i).
            flatMap(r => {
              if (empty)
                e.apply(r)
              else
                Future.successful(r)
            })(defaultExecutionContext)
        }
      }
    
    }
    

    如何包装搜索并使其懒惰

    class LazyEnumerator[E](e: => Enumerator[E]) extends Enumerator[E] {
      lazy _e = e
      def apply[A](i: Iteratee[E, A]) = _e.apply(i)
    }
    
    possibleQueries.
        map(query => new LazyEnumerator(searchableCollection.find(query))).
        foldLeft(Enumerator.empty[JsObject])({ (e1, e2) => e1.andThen(e2) }) through 
        take[JsObject](MAX_AMOUNT)