ElasticSwift
Project Status
This project is actively in developement, more information will be made available as project progresses.
If you'd like to contribute pull requests are welcome.
-
Platform support for macOS, iOS & linux.
-
Query DSL builders and helpers similar to elasticsearch Java client. Check the table below to see full list of avaiable QueryBuilders
Project Goal
Our goal is to make a very Swifty and high-performant elasticsearch client.
High-performant means providing end user's response under 100ms not including the time elasticsearch took to process the request.
Installation
CocoaPods
CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:
$ gem install cocoapods
CocoaPods 1.6.0+ is required to build ElasticSwift.
To integrate Elasticswift into your Xcode project using CocoaPods, specify it in your Podfile
:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!
target '<Your Target Name>' do
pod 'ElasticSwift', '~> 1.0.0-alpha.10'
pod 'ElasticSwiftCore', '~> 1.0.0-alpha.10'
pod 'ElasticSwiftQueryDSL', '~> 1.0.0-alpha.10'
pod 'ElasticSwiftCodableUtils', '~> 1.0.0-alpha.10'
pod 'ElasticSwiftNetworking', '~> 1.0.0-alpha.10'
end
Note:- ElasticSwiftNetworkingNIO is not available as a pod
Then, run the following command:
$ pod install
Swift Package Manager
The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift compiler. It is in early development, but ElasticSwift does support its use on supported platforms.
Once you have your Swift package set up, adding ElasticSwift as a dependency is as easy as adding it to the dependencies value of your Package.swift.
dependencies: [
.package(url: "https://github.com/pksprojects/ElasticSwift.git", from: "1.0.0-alpha.10")
]
Usage
Client
Creating Settings
& ElasticClient
.
Using ElasticSwiftNetworking
(URLSession
based implementation)
import ElasticSwift
import ElasticSwiftNetworking
var settings = Settings(forHost: "http://localhost:9200", adaptorConfig: URLSessionAdaptorConfiguration.default) // Creates default settings for client
var client = ElasticClient(settings: settings) // Creates client with specified settings
Using ElasticSwiftNetworkingNIO
(SwiftNIO/AsyncHTTPClient
based implementation)
import ElasticSwift
import ElasticSwiftNetworkingNIO
var settings = Settings(forHost: "http://localhost:9200", adaptorConfig: AsyncHTTPClientAdaptorConfiguration.default) // Creates default settings for client
var client = ElasticClient(settings: settings) // Creates client with specified settings
Add Elasticsearch credentials
let cred = BasicClientCredential(username: "elastic", password: "elastic")
let settings = Settings(forHost: "http://localhost:9200", withCredentials: cred, adaptorConfig: AsyncHTTPClientAdaptorConfiguration.default)
Configuring SSL when using ElasticSwiftNetworking
let certPath = "/path/to/certificate.der"
let sslConfig = SSLConfiguration(certPath: certPath, isSelf: true)
let adaptorConfig = URLSessionAdaptorConfiguration(sslConfig: sslConfig)
let settings = Settings(forHosts: ["https://samplehost:port"], withCredentials: cred, adaptorConfig: adaptorConfig)
Index
Create and Delete Index
func createHandler(_ result: Result<CreateIndexResponse, Error>) -> Void {
switch result {
case .failure(let error):
print("Error", error)
case .success(let response):
print("Response", response)
}
}
// creating index
let createIndexRequest = CreateIndexRequest(name: "indexName")
client.indices.create(createIndexRequest, completionHandler: createHandler) // executes request
// delete index
func deleteHandler(_ response: DeleteIndexResponse?, _ error: Error?) -> Void {
switch result {
case .failure(let error):
print("Error", error)
case .success(let response):
print("Response", response)
}
}
let deleteIndexRequest = DeleteIndexRequest(name: "indexName")
client.indices.delete(deleteIndexRequest, completionHandler: deleteHandler) // executes request
Document
Document CRUD
class MyClass: Codable {
var myField: String?
}
// index document
func indexHandler(_ result: Result<IndexResponse, Error>) -> Void {
switch result {
case .failure(let error):
print("Error", error)
case .success(let response):
print("Response", response)
}
}
let mySource = MyClass()
mySource.myField = "My value"
let indexRequest = try IndexRequestBuilder<MyClass>()
.set(index: "indexName")
.set(type: "type")
.set(id: "id")
.set(source: mySource)
.build()
client.index(indexRequest, completionHandler: indexHandler)
// get document
func getHandler(_ result: Result<GetResponse<MyClass>, Error>) -> Void {
switch result {
case .failure(let error):
print("Error", error)
case .success(let response):
print("Response", response)
}
}
let getRequest = GetRequestBuilder<MyClass>()
.set(id: "id")
.set(index: "indexName")
.set(type: "type")
.build()
client.get(getRequest, completionHandler: getHandler)
// delete document
func deleteHandler(_ result: Result<DeleteResponse, Error>) -> Void {
switch result {
case .failure(let error):
print("Error", error)
case .success(let response):
print("Response", response)
}
}
let deleteRequest = try DeleteRequestBuilder()
.set(index: "indexName")
.set(type: "type")
.set(id: "id")
.build()
client.delete(deleteRequest, completionHandler: deleteHandler)
Query
Currently not all QueryBuilders are available. Future releases will add support for additional QueryBuilders. Check below for details
let builder = QueryBuilders.boolQuery()
let mustMatch = try QueryBuilders.matchQuery().match(field: "fieldName", value: "value").build()
let mustNotMatch = try QueryBuilders.matchQuery().match(field: "fieldName", value: "value").build()
builder.must(query: mustMatch)
builder.mustNot(query: mustNotMatch)
let boolQuery = try builder.build()
Search
Creating simple search request.
func handler(_ result: Result<SearchResponse<Message>, Error>) -> Void {
switch result {
case .failure(let error):
print("Error", error)
case .success(let response):
print("Response", response)
}
}
let queryBuilder = QueryBuilders.boolQuery()
let match = try QueryBuilders.matchQuery().match(field: "myField", value: "MySearchValue").build()
queryBuilder.must(query: match)
let query = try queryBuilder.build()
let sort = SortBuilders.fieldSort("msg") // use "msg.keyword" as field name in case of text field
.set(order: .asc)
.build()
let request = try SearchRequestBuilder()
.set(indices: "indexName")
.set(types: "type")
.set(query: query)
.set(sort: sort)
.build()
client.search(request, completionHandler: handler)
QueryDSL
Below Table lists all the available search queries with their corresponding QueryBuilder class name and helper method name in the QueryBuilders utility class.
| Search Query | QueryBuilder Class | Method in QueryBuilders | | :--- | :--- | :--- | | ConstantScoreQuery | ConstantScoreQueryBuilder | QueryBuilders.constantScoreQuery() | | BoolQuery | BoolQueryBuilder | QueryBuilders.boolQuery() | | DisMaxQuery | DisMaxQueryBuilder | QueryBuilders.disMaxQuery() | | FunctionScoreQuery | FunctionScoreQueryBuilder | QueryBuilders.functionScoreQuery() | | BoostingQuery | BoostingQueryBuilder | QueryBuilders.boostingeQuery() | | MatchQuery | MatchQueryBuilder | QueryBuilders.matchQuery() | | MatchPhraseQuery | MatchPhraseQueryBuilder | QueryBuilders.matchPhraseQuery() | | MatchPhrasePrefixQuery | MatchPhrasePrefixQueryBuilder | QueryBuilders.matchPhrasePrefixQuery() | | MultiMatchQuery | MultiMatchQueryBuilder | QueryBuilders.multiMatchQuery() | | CommonTermsQuery | CommonTermsQueryBuilder | QueryBuilders.commonTermsQuery() | | QueryStringQuery | QueryStringQueryBuilder | QueryBuilders.queryStringQuery() | | SimpleQueryStringQuery | SimpleQueryStringQueryBuilder | QueryBuilders.simpleQueryStringQuery() | | MatchAllQuery | MatchAllQueryBuilder | QueryBuilders.matchAllQuery() | | MatchNoneQuery | MatchNoneQueryBuilder | QueryBuilders.matchNoneQuery() | | TermQuery | TermQueryBuilder | QueryBuilders.termQuery() | | TermsQuery | TermsQueryBuilder | QueryBuilders.termsQuery() | | RangeQuery | RangeQueryBuilder | QueryBuilders.rangeQuery() | | ExistsQuery | ExistsQueryBuilder | QueryBuilders.existsQuery() | | PrefixQuery | PrefixQueryBuilder | QueryBuilders.prefixQuery() | | WildCardQuery | WildCardQueryBuilder | QueryBuilders.wildCardQuery() | | RegexpQuery | RegexpQueryBuilder | QueryBuilders.regexpQuery() | | FuzzyQuery | FuzzyQueryBuilder | QueryBuilders.fuzzyQuery() | | TypeQuery | TypeQueryBuilder | QueryBuilders.typeQuery() | | IdsQuery | IdsQueryBuilder | QueryBuilders.idsQuery() |
Github
link |
Stars: 23 |
Help us keep the lights on
Dependencies
Releases
v1.0.0-alpha.10 - Nov 11, 2019
- Make Query, Script, Sort & ScoreFunction conform to Codable & Equatable and are value types.
- Refactor Request body serialization using Codable.
- Body of HttpResponse is now Data.
- HttpRequest & HttpResponse are now value types.
- Update Dependencies.
- Add build on Linux.
- [refactor] EncodableUtils new common protocol ValueWrapper for CodableValue, DecodableValue and EncodableValue, rename NullValue to NilValue, removed protocols EncodableWrapper, DecodableWrapper and CodableWrapper
- [chore] add swift-log to unit tests
- [fix] typo in logger label in ElasticClient
- Split SwiftNIO and URLSession based networking layer into individual modules ElasticSwiftNetworkingNIO & ElasticSwiftNetworking as respectively.
- add podspec for ElasticSwiftNetworkingNIO
- add travis linux build for swift-5.1
- add Ubuntu 16.04 [swift-5.0.3, swift-5.1] build
- Doesn't use URLSession based networking implementation on Linux.
- [fix] make MultiGetRequest consistent as other requests
- _termvectors request support.
- Add analyzer, store, termVector to Index MappingMetaData
- Bulk Request Support
- MultiTermVector Request Support
- TermVector Request Support
- ReIndex Request Support
- MultiGet Request Support
- Standardized Builders
- AsyncHTTPClient Based
ElasticSwiftNetworkingNIO
v1.0.0-alpha.9 - Aug 1, 2019
ChangeLog
- (#31)
UpdateRequest
support. - (#33)
UpdateByQueryRequest
support. - (#32)
DeleteByQyeryRequest
support. - (#40 ) Split Lib into following modules:-
ElasticSwiftCore
-> Core module with common/shared protocols, class, struct, enum.ElasticSwiftQueryDSL
-> Query and QueryBuilders.ElasticSwiftNetworking
-> Networking layer of the lib.ElasticSwiftCodableUtils
-> CodableUtilsElasticSwift
-> main lib depends on all other modules. - (#44) fix
SearchResponse
serialization. - Ability to initialize
DefaultSerializer
with customJSONEncoder
&/orJSONDecoder
. - Improvements to
Settings
HTTPSettings
helper enum.ClientCredential
protocol- Improved support for plugable clients with
HTTPClientAdaptor
&ManagedHTTPClientAdaptor
protocols - fix generic type leakage from response to request.
v1.0.0-alpha.8 - Jul 15, 2019
ChangeLog
- Support for index aliases, mapping, and setting in
CreateIndexRequest
. - Removed unnecessary
optionals?
for values that will always be present in response. - Fixes to response serializations.
- QueryParams support for some requests to avoid unnecessary usage of
RequestOptions
. IndexExistsRequest
support.- Refactor
ElasticClient
class. - Fix typos in
README.md
- Improved
defaultConverter
. - Improved Error handling and reporting.
- Change protocol constraint from Codable to
Encodable
&Decodable
forencode(_:)
&decode(data:)
respectively. - Add serializing error types
EncodingError
&DecodingError
DefaultSerializer
test cases
Linux
- This is the first release tested to be working on
Linux
(Ubuntu 18.04). - Tested to be working with Server-Side frameworks
Kitura
&Vapor
examples will be available soon.
Contributions
- @lubbo thanks for awesome
PR
v1.0.0-alpha.7 - Jul 4, 2019
ChangeLog
- Rework of the underlying networking layer.
- This provides the user with the ability to use HttpClient of their choice.
swift-nio
andURLSession
based implementations are available out-of-the-box.URLSession
based client as default on iOS, tvOS, and watchOS for backward compatibility.- Improved and simpler API.
- Mechanism to allow the user to use serializer of choice.
- Way to pass custom Response Converter to get full control on response conversion.
- A default Response Converter based on Codable.
v1.0.0-alpha.6 - Jun 30, 2019
Changelog
- Revert pod compatibility for iOS 10+, macOS 10.10+, tvOS 10+, watchOS 3+
- swift 5.0 required