CloudSearch является сервисом полнотекстового поиска в облаке Amazon’а . То есть, что-то вроде ElasticSearch или Solr, который не обязательно понимать, главное любить и кормить вовремя не нужно настраивать и поддерживать, главное вовремя оплачивать. В этой заметке будет показан простой пример использования Amazon CloudSearch на языке Scala.

Настройка Amazon CloudSearch через веб-интерфейс до безобразия проста, поэтому не будем на ней даже останавливаться, тем более, что веб-интерфейсы все равно часто меняются.

А вот, собственно, и код:

import com. amazonaws . auth . BasicAWSCredentials
import com. amazonaws . services . cloudsearchdomain . _
import com. amazonaws . services . cloudsearchdomain . model . _
import org. json4s . _
import org. json4s . jackson . JsonMethods . _

import java. io . _
import java. nio . charset . _
import scala. collection . JavaConverters . _

object CloudSearchExample extends App {
val cloudsearchEndpoint = «https://abcefg.cloudsearch.amazonaws.com»
val accessKey = «ACCESSKEY123»
val secretKey = «SECRETKEY456»

val credentials = new BasicAWSCredentials ( accessKey, secretKey )
val client = new AmazonCloudSearchDomainClient ( credentials )
client. setEndpoint ( cloudsearchEndpoint )

val docType = «message»
val docTypeLen = docType. length

// ——— upload ———

{
val j = compact ( render ( JArray ( List (
JObject ( List (
«type» > JString ( «add» ) ,
«id» > JString ( s «${docType}23456» ) ,
«fields» > JObject ( List (
«text» > JString ( «test test» ) ,
«type» > JString ( docType )
) )
) )
) ) ) )

val bytes = j. getBytes ( StandardCharsets. UTF_8 )
val stream = new ByteArrayInputStream ( bytes )

val req = new UploadDocumentsRequest ( )
req. setContentType ( «application/json» )
req. setContentLength ( bytes. length . toLong )
req. setDocuments ( stream )

val res = client. uploadDocuments ( req )
println ( res. toString )
}

// ——— search ———

{
val req = new SearchRequest
req. setQuery ( s «»»text:»test test» AND type:»${docType}» «»» )
req. setQueryParser ( QueryParser. Lucene )

val res = client. search ( req )
val hits = res. getHits . getHit . asScala

val ids = hits. map ( _ . getId ) . filter ( _ . startsWith ( docType ) )
. map ( _ . drop ( docTypeLen ) . toLong )

println ( s «Ids: $ids» )
}
}

Как видите, приходится построить немного JSON-а вручную, воспользовавшись уже знакомым нам json4s . Обратите внимание, что в строке:

req. setQuery ( s «»»text:»test test» AND type:»${docType}» «»» )

… слово AND обязательно должно быть в верхнем регистре, иначе запрос просто тихо не найдет ни одного документа.

В остальном, как мне кажется, пример предельно прост и не нуждается в особых пояснениях. Шлется запрос на добавление:

«type» > JString ( «add» )

… документа с определенным id и полями, затем посылается запрос на поиск документа по полям. Возвращается список наиболее релевантных документов, из него выдираются id найденных документов и показываются пользователю. В реальном приложении вам, понятное дело, придется завести пул с нитками ОС и обернуть все хождения в CloudSearch в футуры , так как вряд ли вы хотите просто брать и делать блокирующие вызовы в своем бэкенде.

А работаете ли вы с CloudSearch или иной системой полнотекстового поиска?

Дополнение: Также вас может заинтересовать пост Основы полнотекстового поиска в PostgreSQL .

EnglishRussianUkrainian