Общая функция ReactiveMongo

У меня есть несколько таких функций:

  import reactivemongo.play.json.collection.JSONCollection

  def quotesFuture: Future[JSONCollection] = database.map(_.collection[JSONCollection]("quotes"))

 1:  def getByAuthor(author: String) = Action.async {
 2:    quotesFuture.flatMap{ quotes =>
 3:      quotes
 4:        .find(obj("author" -> author))
 5:        .cursor[JsObject](ReadPreference.primary)
 6:        .collect[List](maxQuotes)
 7:        .map(q => Ok(Json.toJson(q)))
 8:    }
 9:  }
10:
11:  def search(term: String) = Action.async {
12:    quotesFuture.flatMap{ quotes =>
13:      quotes
14:        .find(obj("$text" -> obj("$search" -> term)), textScore)
15:        .sort(textScore)
16:        .cursor[JsObject](ReadPreference.primary)
17:        .collect[List](maxQuotes)
18:        .map(q => Ok(Json.toJson(q)))
19:    }
20:  }

но много повторений; единственное, что меняется, это поиск и сортировка, поэтому я хотел бы провести рефакторинг следующим образом:

100:  def getByAuthor(author: String) = getList { quotes =>
101:    quotes
102:      .find(obj("author" -> author))
103:  }
104:
105:  def search(term: String) = getList { quotes =>
106:    quotes
107:      .find(obj("$text" -> obj("$search" -> term)), textScore)
108:      .sort(textScore)
109:  }
110:
111:  def getList(query: (JSONCollection) => ???) = Action.async {
112:    quotesFuture.flatMap{ quotes =>
113:      query(quotes)
114:        .cursor[JsObject](ReadPreference.primary)
115:        .collect[List](maxQuotes)
116:        .map(q => Ok(Json.toJson(q)))
117:    }
118:  }

Вопрос в том, каким должен быть ??? в строке 111?

Когда мы просим IntelliJ извлечь метод из строк 14-15, он создает следующее

  def tempdef(term: String, quotes: JSONCollection): GenericQueryBuilder[quotes.pack.type]#Self = {
    quotes
      .find(obj("$text" -> obj("$search" -> term)), textScore)
      .sort(textScore)
  }

Тип результата, предложенный IntelliJ, довольно пугающий. Итак, ??? в строке 111 должно быть GenericQueryBuilder[quotes.pack.type]#Self, но это зависит от переменной quotes. Что я должен заменить ???, чтобы это сработало?

Используя IntelliJ, я вижу, что quotes.pack относится к:

case class JSONCollection(...) {...
  val pack = JSONSerializationPack
}

Я попытался заменить ??? в строке 111 на JSONSerializationPack.type, и он компилируется и работает.

Однако просмотр деталей реализации JSONCollection является обманом, и это может перестать работать, если реализация JSONCollection изменится.

Итак, каким должно быть ??? в строке 111?

В противном случае, видите ли вы более простой способ убрать дублирование кода в этом примере?


person David Portabella    schedule 16.08.2016    source источник


Ответы (1)


Я бы посоветовал вашим getByAuthor и search вернуть Cursor[JsObject], что позволяет им иметь разные ReadPreference и работать с независимыми типами (в отличие от построителя запросов, который зависит от базового пакета сериализации коллекции, что не понимается ИДЕ).

импортировать реактивный mongo.api.Cursor

def getByAuthor(author: String): Cursor[JsObject] = ???

def search(term: String): Cursor[JsObject] = ???

def getList(cursor: JSONCollection => Cursor[JsObject] = Action.async {
  quotesFuture.flatMap { quotes =>
    val c: Cursor[JsObject] = cursor(quotes)
    ???
  }
person cchantep    schedule 16.08.2016
comment
Таким образом, 1_. мне по-прежнему нужно каждый раз дублировать cursor[JsObject](ReadPreference.primary), но это уже улучшение, спасибо. - person David Portabella; 16.08.2016
comment
Я не понимаю фразу "береги себя". пример компилируется и работает. не могли бы вы перефразировать это? - person David Portabella; 16.08.2016