# django-elasticindex
Django用 Elasticsearch の薄いラッパー
## できること
・Django モデルと対応させ、Elasticsearch にデータを流し込むことができます。
(モデルとの対応は必須ではありません)
・Djangoクエリセットに少し近い形式で、クエリを発行することができます。
クエリには Elasticsearch のクエリに用いるための辞書をそのまま用いる、
あまり分厚くない(お節介の少ない)インターフェイスとなっています。
## Install
```
$ pip install django-elasticindex
```
## サンプルコード
リポジトリ内の、tests ディレクトリに動作するコードがあります。
### 1. Djangoのモデルの定義
models.py
```python
from django.db import models
class DummyModel(models.Model):
key = models.CharField(max_length=20, primary_key=True)
value = models.TextField()
```
### 2. ElasticDocument クラスの定義
```python
from elasticindex.models import ElasticDocument, ElasticDocumentField as F
class DummyESDocument(ElasticDocument):
INDEX = "elasticindex_test"
ALLOW_KUROMOJI = False
source_model = DummyModel
key = F(mapping={"type": "string", "index": "not_analized"})
value = F(mapping={"type": "string"})
```
### 3. データ流し込みバッチ
```python
DummyESDocument.rebuild_index()
```
rebuild_index() を実行すると、Elasticsearch 上にインデックスを作成し(存在しない場合)、
対応するDjango モデル ( DummyModel ) の全データを DB から読み出し、Elasticsearch に入れます。
#### 3-1. 特定のモデルインスタンスのデータを入れる
```python
i = DummyModel.objects.get(key="xxx")
DummyESDocument.rebuild_index_by_source_model(i)
```
これで、1レコードの更新ができます
### 4. 検索
#### 4-1. シンプルな検索
```python
results = DummyESDocument.objects.query({"match": {"key": "jumps"}})
```
results は、ElasticQuerySet のインスタンスです。
```python
result = list(results)[0]
```
検索を行い、result には DummyESDocument のインスタンスが入ります。
#### 4-2. OR検索
```python
qs = DummyESDocument.objects.query(
{"bool": {
"should": [
{"match": {"value": "dogs"}},
{"match": {"value": "fox"}},
]}})
```
query は Elasticsearch の query をそのまま使います。
#### 4-3. ソート順変更
```python
qs = DummyESDocument.objects.query({...})
qs = qs.order_by({"key": "desc"})
```
Django のクエリセットのように、order_by をメソッドチェーンしてください。
#### 4-4. 結果のスライシング
```python
qs = DummyESDocument.objects.query({...})
results = qs[:100]
```
こちらも、Djangoのクエリセットのように、Python のスライシングを行うと範囲指定できます。
実行したタイミングでクエリが評価され、HTTPリクエストが発行されます。
また、.limit(), .offset() というメソッドもあり、メソッドチェーンで使えます。
```python
qs = DummyESDocument.objects.query({...})
qs = qs.limit(20).offset(40).order_by({"created_at": "desc"})
```
#### 4-5. パジネーション
Django のクエリセットのように、
```python
from django.core.paginator import Paginator
qs = DummyESDocument.objects.query({...})
paginator = Paginator(qs, 100)
page = paginator.page(1)
page.object_list...
```
Django の Paginator を用いてのパジネーションができます。
### 5. 設定
#### 5-1. ローカルエリアの ES を指定する場合
settings.py
```python
ELASTICINDEX_HOSTS = [{'host': '127.0.0.1', 'port': 9200}]
```
ELASTICINDEX_HOSTS を指定してください。
#### 5-2. Amazon Elasticsearch Service を使う場合
```python
ELASTICINDEX_HOSTS = [
{'host': 'xxxxxx.ap-northeast-1.es.amazonaws.com',
'port': 443}]
ELASTICINDEX_AWS_IAM = {
'access_id': 'AWSACCESSID',
'secret_key': 'AwsSecretKey******',
'region': 'ap-northeast-1',
}
```
Amazon ES へのアクセスを許可した IAM のクレデンシャルを settings に書いてください。
Amazon ES へのアクセス許可方法(IAMの作成方法)は Qiita に書きました
Amazon Elasticsearch Service を Python クライアントで、IAM アカウントを作ってセキュアにアクセスする - Qiita
http://qiita.com/ytyng/items/7c90c0b141aad9a12b38
### 6. テスト
クローンしたリポジトリで
```shell
$ docker run --rm -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.9.3
```
```shell
$ pip install -r requirements.txt
$ make test
```
実際に ES にアクセスを行う。
ESがローカルの 9200 ポートで動作していない場合は、local_settings.py を作成
local_settings.py
```python
ELASTICINDEX_HOSTS = [{'host': 'my-elasticsearch-host', 'port': 9200}]
```
Raw data
{
"_id": null,
"home_page": "https://github.com/ytyng/django-elasticindex",
"name": "django-elasticindex",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": "Elasticsearch, Django, Python",
"author": "ytyng",
"author_email": "ytyng@live.jp",
"download_url": "https://files.pythonhosted.org/packages/d6/5b/f2e37228aab986ca4a952741f18686d03785a738bad400553785cb7ff4e3/django-elasticindex-0.2.2.tar.gz",
"platform": null,
"description": "# django-elasticindex\n\nDjango\u7528 Elasticsearch \u306e\u8584\u3044\u30e9\u30c3\u30d1\u30fc\n\n\n## \u3067\u304d\u308b\u3053\u3068\n\n\u30fbDjango \u30e2\u30c7\u30eb\u3068\u5bfe\u5fdc\u3055\u305b\u3001Elasticsearch \u306b\u30c7\u30fc\u30bf\u3092\u6d41\u3057\u8fbc\u3080\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\n\n(\u30e2\u30c7\u30eb\u3068\u306e\u5bfe\u5fdc\u306f\u5fc5\u9808\u3067\u306f\u3042\u308a\u307e\u305b\u3093)\n\n\u30fbDjango\u30af\u30a8\u30ea\u30bb\u30c3\u30c8\u306b\u5c11\u3057\u8fd1\u3044\u5f62\u5f0f\u3067\u3001\u30af\u30a8\u30ea\u3092\u767a\u884c\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\n\n\u30af\u30a8\u30ea\u306b\u306f Elasticsearch \u306e\u30af\u30a8\u30ea\u306b\u7528\u3044\u308b\u305f\u3081\u306e\u8f9e\u66f8\u3092\u305d\u306e\u307e\u307e\u7528\u3044\u308b\u3001\n\u3042\u307e\u308a\u5206\u539a\u304f\u306a\u3044(\u304a\u7bc0\u4ecb\u306e\u5c11\u306a\u3044)\u30a4\u30f3\u30bf\u30fc\u30d5\u30a7\u30a4\u30b9\u3068\u306a\u3063\u3066\u3044\u307e\u3059\u3002\n\n\n\n## Install\n```\n$ pip install django-elasticindex\n```\n\n## \u30b5\u30f3\u30d7\u30eb\u30b3\u30fc\u30c9\n\n\u30ea\u30dd\u30b8\u30c8\u30ea\u5185\u306e\u3001tests \u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306b\u52d5\u4f5c\u3059\u308b\u30b3\u30fc\u30c9\u304c\u3042\u308a\u307e\u3059\u3002\n\n### 1. Django\u306e\u30e2\u30c7\u30eb\u306e\u5b9a\u7fa9\n\nmodels.py\n\n```python\nfrom django.db import models\n\nclass DummyModel(models.Model):\n key = models.CharField(max_length=20, primary_key=True)\n value = models.TextField()\n```\n\n### 2. ElasticDocument \u30af\u30e9\u30b9\u306e\u5b9a\u7fa9\n\n\n```python\nfrom elasticindex.models import ElasticDocument, ElasticDocumentField as F\n\nclass DummyESDocument(ElasticDocument):\n INDEX = \"elasticindex_test\"\n ALLOW_KUROMOJI = False\n\n source_model = DummyModel\n\n key = F(mapping={\"type\": \"string\", \"index\": \"not_analized\"})\n value = F(mapping={\"type\": \"string\"})\n```\n\n### 3. \u30c7\u30fc\u30bf\u6d41\u3057\u8fbc\u307f\u30d0\u30c3\u30c1\n\n```python\nDummyESDocument.rebuild_index()\n```\n\nrebuild_index() \u3092\u5b9f\u884c\u3059\u308b\u3068\u3001Elasticsearch \u4e0a\u306b\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u4f5c\u6210\u3057(\u5b58\u5728\u3057\u306a\u3044\u5834\u5408)\u3001\n\u5bfe\u5fdc\u3059\u308bDjango \u30e2\u30c7\u30eb ( DummyModel ) \u306e\u5168\u30c7\u30fc\u30bf\u3092 DB \u304b\u3089\u8aad\u307f\u51fa\u3057\u3001Elasticsearch \u306b\u5165\u308c\u307e\u3059\u3002\n\n\n#### 3-1. \u7279\u5b9a\u306e\u30e2\u30c7\u30eb\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u30c7\u30fc\u30bf\u3092\u5165\u308c\u308b\n\n```python\ni = DummyModel.objects.get(key=\"xxx\")\nDummyESDocument.rebuild_index_by_source_model(i)\n```\n\n\u3053\u308c\u3067\u30011\u30ec\u30b3\u30fc\u30c9\u306e\u66f4\u65b0\u304c\u3067\u304d\u307e\u3059\n\n\n### 4. \u691c\u7d22\n\n#### 4-1. \u30b7\u30f3\u30d7\u30eb\u306a\u691c\u7d22\n\n```python\nresults = DummyESDocument.objects.query({\"match\": {\"key\": \"jumps\"}})\n```\n\nresults \u306f\u3001ElasticQuerySet \u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3067\u3059\u3002\n\n```python\nresult = list(results)[0]\n```\n\n\u691c\u7d22\u3092\u884c\u3044\u3001result \u306b\u306f DummyESDocument \u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304c\u5165\u308a\u307e\u3059\u3002\n\n\n#### 4-2. OR\u691c\u7d22\n\n```python\nqs = DummyESDocument.objects.query(\n {\"bool\": {\n \"should\": [\n {\"match\": {\"value\": \"dogs\"}},\n {\"match\": {\"value\": \"fox\"}},\n\n ]}})\n```\n\nquery \u306f Elasticsearch \u306e query \u3092\u305d\u306e\u307e\u307e\u4f7f\u3044\u307e\u3059\u3002\n\n\n#### 4-3. \u30bd\u30fc\u30c8\u9806\u5909\u66f4\n\n```python\nqs = DummyESDocument.objects.query({...})\nqs = qs.order_by({\"key\": \"desc\"})\n```\n\nDjango \u306e\u30af\u30a8\u30ea\u30bb\u30c3\u30c8\u306e\u3088\u3046\u306b\u3001order_by \u3092\u30e1\u30bd\u30c3\u30c9\u30c1\u30a7\u30fc\u30f3\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\n#### 4-4. \u7d50\u679c\u306e\u30b9\u30e9\u30a4\u30b7\u30f3\u30b0\n\n```python\nqs = DummyESDocument.objects.query({...})\nresults = qs[:100]\n```\n\n\u3053\u3061\u3089\u3082\u3001Django\u306e\u30af\u30a8\u30ea\u30bb\u30c3\u30c8\u306e\u3088\u3046\u306b\u3001Python \u306e\u30b9\u30e9\u30a4\u30b7\u30f3\u30b0\u3092\u884c\u3046\u3068\u7bc4\u56f2\u6307\u5b9a\u3067\u304d\u307e\u3059\u3002\n\u5b9f\u884c\u3057\u305f\u30bf\u30a4\u30df\u30f3\u30b0\u3067\u30af\u30a8\u30ea\u304c\u8a55\u4fa1\u3055\u308c\u3001HTTP\u30ea\u30af\u30a8\u30b9\u30c8\u304c\u767a\u884c\u3055\u308c\u307e\u3059\u3002\n\n\u307e\u305f\u3001.limit(), .offset() \u3068\u3044\u3046\u30e1\u30bd\u30c3\u30c9\u3082\u3042\u308a\u3001\u30e1\u30bd\u30c3\u30c9\u30c1\u30a7\u30fc\u30f3\u3067\u4f7f\u3048\u307e\u3059\u3002\n\n```python\nqs = DummyESDocument.objects.query({...})\nqs = qs.limit(20).offset(40).order_by({\"created_at\": \"desc\"})\n```\n\n#### 4-5. \u30d1\u30b8\u30cd\u30fc\u30b7\u30e7\u30f3\n\nDjango \u306e\u30af\u30a8\u30ea\u30bb\u30c3\u30c8\u306e\u3088\u3046\u306b\u3001\n\n```python\nfrom django.core.paginator import Paginator\n\nqs = DummyESDocument.objects.query({...})\npaginator = Paginator(qs, 100)\n\npage = paginator.page(1)\n\npage.object_list...\n```\n\nDjango \u306e Paginator \u3092\u7528\u3044\u3066\u306e\u30d1\u30b8\u30cd\u30fc\u30b7\u30e7\u30f3\u304c\u3067\u304d\u307e\u3059\u3002\n\n\n### 5. \u8a2d\u5b9a\n\n#### 5-1. \u30ed\u30fc\u30ab\u30eb\u30a8\u30ea\u30a2\u306e ES \u3092\u6307\u5b9a\u3059\u308b\u5834\u5408\n\nsettings.py\n\n```python\nELASTICINDEX_HOSTS = [{'host': '127.0.0.1', 'port': 9200}]\n```\n\nELASTICINDEX_HOSTS \u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\n\n#### 5-2. Amazon Elasticsearch Service \u3092\u4f7f\u3046\u5834\u5408\n\n```python\nELASTICINDEX_HOSTS = [\n {'host': 'xxxxxx.ap-northeast-1.es.amazonaws.com',\n 'port': 443}]\nELASTICINDEX_AWS_IAM = {\n 'access_id': 'AWSACCESSID',\n 'secret_key': 'AwsSecretKey******',\n 'region': 'ap-northeast-1',\n}\n```\n\nAmazon ES \u3078\u306e\u30a2\u30af\u30bb\u30b9\u3092\u8a31\u53ef\u3057\u305f IAM \u306e\u30af\u30ec\u30c7\u30f3\u30b7\u30e3\u30eb\u3092 settings \u306b\u66f8\u3044\u3066\u304f\u3060\u3055\u3044\u3002\n\nAmazon ES \u3078\u306e\u30a2\u30af\u30bb\u30b9\u8a31\u53ef\u65b9\u6cd5(IAM\u306e\u4f5c\u6210\u65b9\u6cd5)\u306f Qiita \u306b\u66f8\u304d\u307e\u3057\u305f\n\nAmazon Elasticsearch Service \u3092 Python \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3067\u3001IAM \u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u4f5c\u3063\u3066\u30bb\u30ad\u30e5\u30a2\u306b\u30a2\u30af\u30bb\u30b9\u3059\u308b - Qiita\n\nhttp://qiita.com/ytyng/items/7c90c0b141aad9a12b38\n\n\n### 6. \u30c6\u30b9\u30c8\n\n\u30af\u30ed\u30fc\u30f3\u3057\u305f\u30ea\u30dd\u30b8\u30c8\u30ea\u3067\n\n```shell\n$ docker run --rm -p 9200:9200 -p 9300:9300 -e \"discovery.type=single-node\" elasticsearch:7.9.3\n```\n\n```shell\n$ pip install -r requirements.txt\n$ make test\n```\n\n\u5b9f\u969b\u306b ES \u306b\u30a2\u30af\u30bb\u30b9\u3092\u884c\u3046\u3002\nES\u304c\u30ed\u30fc\u30ab\u30eb\u306e 9200 \u30dd\u30fc\u30c8\u3067\u52d5\u4f5c\u3057\u3066\u3044\u306a\u3044\u5834\u5408\u306f\u3001local_settings.py \u3092\u4f5c\u6210\n\nlocal_settings.py\n\n```python\nELASTICINDEX_HOSTS = [{'host': 'my-elasticsearch-host', 'port': 9200}]\n```",
"bugtrack_url": null,
"license": "BSD",
"summary": "Shallow elasticsearch wrapper on Django",
"version": "0.2.2",
"project_urls": {
"Homepage": "https://github.com/ytyng/django-elasticindex"
},
"split_keywords": [
"elasticsearch",
" django",
" python"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d65bf2e37228aab986ca4a952741f18686d03785a738bad400553785cb7ff4e3",
"md5": "056064330337b6bb77a9acb4ca72d62a",
"sha256": "4476596f5ba8625a86ffee4730717ced9f0eb342128c24e9d4bcb8065b460a23"
},
"downloads": -1,
"filename": "django-elasticindex-0.2.2.tar.gz",
"has_sig": false,
"md5_digest": "056064330337b6bb77a9acb4ca72d62a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 10367,
"upload_time": "2024-12-09T01:41:51",
"upload_time_iso_8601": "2024-12-09T01:41:51.760028Z",
"url": "https://files.pythonhosted.org/packages/d6/5b/f2e37228aab986ca4a952741f18686d03785a738bad400553785cb7ff4e3/django-elasticindex-0.2.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-09 01:41:51",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ytyng",
"github_project": "django-elasticindex",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "six",
"specs": []
},
{
"name": "elasticsearch",
"specs": []
},
{
"name": "Django",
"specs": []
}
],
"lcname": "django-elasticindex"
}