From 7e8d773ef6b8fd654b5040586d69fe8caf132d3e Mon Sep 17 00:00:00 2001 From: dblock Date: Mon, 16 Oct 2023 12:20:15 -0400 Subject: [PATCH] Added a guide on making raw JSON REST requests. Signed-off-by: dblock --- CHANGELOG.md | 3 +- USER_GUIDE.md | 1 + guides/json.md | 66 +++++++++++++++++++++++++++ samples/json/hello-async.py | 90 +++++++++++++++++++++++++++++++++++++ samples/json/hello.py | 76 +++++++++++++++++++++++++++++++ 5 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 guides/json.md create mode 100755 samples/json/hello-async.py create mode 100755 samples/json/hello.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 41524e8c..96a4b1ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,10 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Added - Added generating imports and headers to API generator ([#467](https://github.com/opensearch-project/opensearch-py/pull/467)) - Added point-in-time APIs (create_pit, delete_pit, delete_all_pits, get_all_pits) and Security Client APIs (health and update_audit_configuration) ([#502](https://github.com/opensearch-project/opensearch-py/pull/502)) -- Added new guide for using index templates with the client ([#531](https://github.com/opensearch-project/opensearch-py/pull/531)) +- Added guide on using index templates ([#531](https://github.com/opensearch-project/opensearch-py/pull/531)) - Added `pool_maxsize` for `Urllib3HttpConnection` ([#535](https://github.com/opensearch-project/opensearch-py/pull/535)) - Added benchmarks ([#537](https://github.com/opensearch-project/opensearch-py/pull/537)) +- Added guide on making raw JSON REST requests ([#542](https://github.com/opensearch-project/opensearch-py/pull/542)) ### Changed - Generate `tasks` client from API specs ([#508](https://github.com/opensearch-project/opensearch-py/pull/508)) - Generate `ingest` client from API specs ([#513](https://github.com/opensearch-project/opensearch-py/pull/513)) diff --git a/USER_GUIDE.md b/USER_GUIDE.md index a56c1235..d52ee205 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -155,6 +155,7 @@ print(response) - [Using a Proxy](guides/proxy.md) - [Index Templates](guides/index_template.md) - [Advanced Index Actions](guides/advanced_index_actions.md) +- [Making Raw JSON REST Requests](guides/json.md) - [Connection Classes](guides/connection_classes.md) ## Plugins diff --git a/guides/json.md b/guides/json.md new file mode 100644 index 00000000..edefa209 --- /dev/null +++ b/guides/json.md @@ -0,0 +1,66 @@ +- [Making Raw JSON REST Requests](#making-raw-json-rest-requests) + - [GET](#get) + - [PUT](#put) + - [POST](#post) + - [DELETE](#delete) + +# Making Raw JSON REST Requests + +The OpenSearch client implements many high-level REST DSLs that invoke OpenSearch APIs. However you may find yourself in a situation that requires you to invoke an API that is not supported by the client. Use `client.transport.perform_request` to do so. See [samples/json](../samples/json) for a complete working sample. + +## GET + +The following example returns the server version information via `GET /`. + +```python +info = client.transport.perform_request('GET', '/') +print(f"Welcome to {info['version']['distribution']} {info['version']['number']}!") +``` + +Note that the client will parse the response as JSON when appropriate. + +## PUT + +The following example creates an index. + +```python +index_body = { + 'settings': { + 'index': { + 'number_of_shards': 4 + } + } +} + +client.transport.perform_request("PUT", "/movies", body=index_body) +``` + +Note that the client will raise errors automatically. For example, if the index already exists, an `opensearchpy.exceptions.RequestError: RequestError(400, 'resource_already_exists_exception',` will be thrown. + +## POST + +The following example searches for a document. + +```python +q = 'miller' + +query = { + 'size': 5, + 'query': { + 'multi_match': { + 'query': q, + 'fields': ['title^2', 'director'] + } + } +} + +client.transport.perform_request("POST", "/movies/_search", body = query) +``` + +## DELETE + +The following example deletes an index. + +```python +client.transport.perform_request("DELETE", "/movies") +``` diff --git a/samples/json/hello-async.py b/samples/json/hello-async.py new file mode 100755 index 00000000..aa4840c4 --- /dev/null +++ b/samples/json/hello-async.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python + +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. + +import asyncio + +from opensearchpy import AsyncOpenSearch + +async def main(): + # connect to OpenSearch + host = 'localhost' + port = 9200 + auth = ('admin', 'admin') # For testing only. Don't store credentials in code. + + client = AsyncOpenSearch( + hosts = [{'host': host, 'port': port}], + http_auth = auth, + use_ssl = True, + verify_certs = False, + ssl_show_warn = False + ) + + try: + info = await client.transport.perform_request('GET', '/') + print(f"Welcome to {info['version']['distribution']} {info['version']['number']}!") + + # create an index + + index_name = 'movies' + + index_body = { + 'settings': { + 'index': { + 'number_of_shards': 4 + } + } + } + + print(await client.transport.perform_request("PUT", f"/{index_name}", body=index_body)) + + # add a document to the index + + document = { + 'title': 'Moneyball', + 'director': 'Bennett Miller', + 'year': '2011' + } + + id = '1' + + print(await client.transport.perform_request("PUT", f"/{index_name}/_doc/{id}?refresh=true", body = document)) + + # search for a document + + q = 'miller' + + query = { + 'size': 5, + 'query': { + 'multi_match': { + 'query': q, + 'fields': ['title^2', 'director'] + } + } + } + + print(await client.transport.perform_request("POST", f"/{index_name}/_search", body = query)) + + # delete the document + + print(await client.transport.perform_request("DELETE", f"/{index_name}/_doc/{id}")) + + # delete the index + + print(await client.transport.perform_request("DELETE", f"/{index_name}")) + + + finally: + await client.close() + +if __name__ == "__main__": + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + loop.run_until_complete(main()) + loop.close() + diff --git a/samples/json/hello.py b/samples/json/hello.py new file mode 100755 index 00000000..d5b8e70f --- /dev/null +++ b/samples/json/hello.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python + +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. + +from opensearchpy import OpenSearch + +# connect to OpenSearch + +host = 'localhost' +port = 9200 +auth = ('admin', 'admin') # For testing only. Don't store credentials in code. + +client = OpenSearch( + hosts = [{'host': host, 'port': port}], + http_auth = auth, + use_ssl = True, + verify_certs = False, + ssl_show_warn = False +) + +info = client.transport.perform_request('GET', '/') +print(f"Welcome to {info['version']['distribution']} {info['version']['number']}!") + +# create an index + +index_name = 'movies' + +index_body = { + 'settings': { + 'index': { + 'number_of_shards': 4 + } + } +} + +print(client.transport.perform_request("PUT", f"/{index_name}", body=index_body)) + +# add a document to the index + +document = { + 'title': 'Moneyball', + 'director': 'Bennett Miller', + 'year': '2011' +} + +id = '1' + +print(client.transport.perform_request("PUT", f"/{index_name}/_doc/{id}?refresh=true", body = document)) + +# search for a document + +q = 'miller' + +query = { + 'size': 5, + 'query': { + 'multi_match': { + 'query': q, + 'fields': ['title^2', 'director'] + } + } +} + +print(client.transport.perform_request("POST", f"/{index_name}/_search", body = query)) + +# delete the document + +print(client.transport.perform_request("DELETE", f"/{index_name}/_doc/{id}")) + +# delete the index + +print(client.transport.perform_request("DELETE", f"/{index_name}"))