Python - Working with the Elasticsearch REST API
- Step 1: Set up a Single Node Opensearch or Elasticsearch Cluster
- Step 2: Create an Index Mapping and Ingest your Data
- Step 3: Testing the Opensearch Rest API using cURL
Search - cURL to Python
curl -XGET "https://localhost:9200/_search?q=Continuous%20Integration&filter_path=took,hits.hits._id,hits.hits._score,hits.hits._source&_source=title&pretty" --insecure -H 'Content-Type: application/json' -u admin
In Python again, I am running into the HTTPS/Certificate issue on localhost and have to add a , verify=False
to the request:
requests.exceptions.SSLError: HTTPSConnectionPool(host='localhost', port=9200): Max retries exceeded with url: /_search?q=Continuous%20Integration&filter_path=took,hits.hits._id,hits.hits._score,hits.hits._source&_source=title&pretty (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)')))
import requests
import json
from requests.auth import HTTPBasicAuth
username = 'admin'
password = 'admin'
response = requests.get('https://localhost:9200/_search?q=Continuous%20Integration&filter_path=took,hits.hits._id,hits.hits._score,hits.hits._source&_source=title', auth = HTTPBasicAuth(username, password), verify=False)
print(response.content)
This returns the correctly filtered byte response:
b'{"took":5,"hits":{"hits":[{"_id":"docs_ci-cd","_score":3.0692163,"_source":{"title":"What is meant by CI/CD?"}},{"_id":"docs_dev-intro","_score":0.7032547,"_source":{"title":"Application Development and Server Operation"}}]}}'
To extract the JSON string:
result = response.content.decode()
print(type(result))
result_dictionary = json.loads(result)
print(type(result_dictionary))
best_match = result_dictionary['hits']['hits'][0]
print(best_match)
This decoded the bytes into a string and extracted the JSON object from it:
<class 'str'>
<class 'dict'>
{'_id': 'docs_ci-cd', '_score': 3.0692163, '_source': {'title': 'What is meant by CI/CD?'}}
Dynamic Search Terms
import requests
import json
from requests.auth import HTTPBasicAuth
from elastic_config import *
def ask_es(query):
url = f'https://{elastic_url}/{elastic_index}/_search?q={query}'
response = requests.get(url, auth = HTTPBasicAuth(elastic_user, elastic_pass), verify=False)
result = response.content.decode()
result_dictionary = json.loads(result)
return result_dictionary
results = ask_es(query='Continuous%20Integration')
for result in results['hits']['hits']:
print(result['_source']['title'])
print(result['_source']['abstract'])
with elastic_config.py
:
elastic_user = 'admin'
elastic_pass = 'admin'
elastic_url = 'localhost:9200'
elastic_index = 'dev_2022_08_20'
Elasticsearch Flask Client
from flask import Flask, render_template, request
import urllib.parse
import requests
import json
elastic_user = 'admin'
elastic_pass = 'admin'
def ask_elastic(query, elastic_url, elastic_index):
url = f'https://{elastic_url}/{elastic_index}/_search?q={query}'
response = requests.get(url, auth = requests.auth.HTTPBasicAuth(elastic_user, elastic_pass), verify=False)
result = response.content.decode()
result_dictionary = json.loads(result)
return result_dictionary
app = Flask(__name__)
@app.route('/', methods=['GET'])
def home_get():
return render_template('index.html')
@app.route('/', methods=['POST'])
def home_post():
elastic_url = request.form['elastic_url']
elastic_index = request.form['elastic_index']
query = request.form['query']
safe_request = urllib.parse.quote(query)
# print(safe_request)
response = ask_elastic(query=safe_request, elastic_url=elastic_url, elastic_index=elastic_index)
results = response['hits']['hits']
return render_template('results.html', query = query, len = len(results), result = results)
app.run(host='0.0.0.0')
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Elastic Flask</title>
</head>
<body>
<header>
<h1>Elasticsearch Client</h1>
</header>
<main>
<p>Enter a search request:</p>
<form method="POST">
<div><p>Elasticsearch URL : </p><input placeholder="Elasticsearch URL" value="localhost:9200" name="elastic_url"></input></div>
<div><p>Elasticsearch Index : </p><input placeholder="Elasticsearch Index" value="dev_2022_08_20" name="elastic_index"></input></div>
<div><p>Search Query : </p><input placeholder="Search Query" name="query"></input></div>
<br/>
<button>Ask Elastic</button>
</form>
</main>
</body>
</html>
results.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Elastic Flask</title>
</head>
<body>
<header>
<h1>Elasticsearch Client</h1>
</header>
<main>
<p>Enter a search request:</p>
<form method="POST">
<div><input value="{{query}}" name="query"></input></div>
<h3>Search Results</h3>
<ol>
{%for i in range(0, len)%}
<li>{{result[i]['_source']['title']}}</li>
{%endfor%}
</ol>
</form>
</main>
</body>
</html>