django-elasticindex


Namedjango-elasticindex JSON
Version 0.2.2 PyPI version JSON
download
home_pagehttps://github.com/ytyng/django-elasticindex
SummaryShallow elasticsearch wrapper on Django
upload_time2024-12-09 01:41:51
maintainerNone
docs_urlNone
authorytyng
requires_pythonNone
licenseBSD
keywords elasticsearch django python
VCS
bugtrack_url
requirements six elasticsearch Django
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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"
}
        
Elapsed time: 0.40534s