We wanted to perform search queries using ElasticSearch and we didn’t want users to query Elasticsearch directly so we decided to make requests with dgraph using custom directive:
Define a schema that matches the result of elastic search
Here is the schema you need:
type ElasticResult @remote {
took: Int
timed_out: Boolean
_shards: Shard_Data
hits: Hits
}
type Shard_Data @remote {
total: Int
successful: Int
skipped: Int
failed: Int
}
type Hits @remote {
max_score: Float
hits: [Hit]
}
type Hit @remote {
_index: String
_source: Doc
}
# This is the structure of your data in ElasticSearch
type Doc @remote {
EpisodeID: String
type: String
title: String
tags: String
}
Prepare authorization header
ElasticSearch uses a username password authentication and we can use pass it by using proper authorization header. You can use this link or postman to generate an authorization header based on your username and password:
For example in Postman you can use Basic Auth
and enter your username and password:
After doing this Postman will generate Authorization header for you:
We will use this header to make requests to ElasticSearch.
Implement Query
We need to make an external http request so we need custom directive Also we need secret headers to pass the authorization header we have to ElasticSearch server. If you look at the document of custom headers you can see that we can pass this header using # Dgraph.Secret
and secretHeaders
.
Also I have used first
and offset
parameters similar to autogenerated queries to tell ElasticSearch how many documents I want.
We have another argument which is phrase
that we are searching for it.
The return type is ElasticSearch
that we implemented in first section.
type Query {
ElasticSearch(
first: Int = 30
offset: Int = 0
phrase: String!
): ElasticResult
@custom(
http: {
url: "https://your_elastic_server_address/your_index/_search"
method: POST
secretHeaders: ["Authorization:Elastic-Search-Token"]
body: "{query: {match: {name_of_your_field_in_elasticsearch: \"$phrase\"}},size: $first,from: $offset}"
}
)
}
# Dgraph.Secret Elastic-Search-Token "Basic ZWxhc3RpYzo3NjgwcTBRR00NEhTMGZoFUEI2WEQ="
Execute Query
After loading this schema we can send a query like this:
query search {
ElasticSearch(offset: 0, first: 2, phrase: "mySearchPhrase") {
took
timed_out
hits {
max_score
hits {
_index
_source {
# These are your fields from elastic search
title
tags
type
}
}
}
}
}
Let me know if I can improve this doc and if I can put it in a better place.