ドキュメントとそれに関連するメタデータを保存する Django Web アプリケーションを構築しています。
メタデータの大部分は基盤となる MySQL データベースに保存され、OCR されたドキュメント テキストは Elasticsearch でインデックス化され、全文検索が可能になります。モデルで見つかった他のいくつかのフィールドにもインデックスを付けている (したがって、二重に格納している) ため、データ モデルを接続して同期するためにdjango-elasticsearch-dslを組み込みました。Haystackの使用を検討していましたが、Elasticsearch の最新バージョンをサポートしていません。
ドキュメントがアプリケーションの管理インターフェイスを介してアップロードされると、post_save シグナルが自動的に Celery 非同期バックグラウンド タスクをトリガーしてOCR を実行し、最終的に抽出されたテキストを Elasticsearch にインデックス付けします。
モデルに全文フィールドが定義されていないことを見て (データベースに CLOB を保存したり検索したりしたくないので、そうしないことを望んでいます)、更新のベスト プラクティスを探しています。私のtasks.pyファイルからの私のElasticsearchドキュメント。django-elasticseach-dsl を使用してそうする方法はないようです (しかし、おそらく私が間違っているのでしょうか?)。
姉妹のdjango-elasticsearch-dsl-drfパッケージを使用して、REST 経由で Elasticsearch とのインターフェースを試みます。
よりバニラのelasticsearch-dsl-pyパッケージ(elasticsearch-pyに基づく)を使用して、アプリケーションをElasticsearchとより大まかに統合します。少なくともモデルに信号を接続したい場合は、もう少し統合コードを書かなければならないので、このアプローチではいくらか「贅沢」を失うでしょう。
ベストプラクティスはありますか? または、私が検討していない別のアプローチですか?
更新 1: @Nielk からの回答を実装しようとすると、OCR されたテキスト (result = "test" in tasks.py below) を ElasticSearch に永続化できますが、MySQL データベースにも永続化されます。基本的に Submission.rawtext を ElasticSearch へのパススルーとして構成する方法について、私はまだ混乱しています。
models.py:
class Submission(models.Model):
rawtext = models.TextField(null=True, blank=True)
...
def type_to_string(self):
return ""
ドキュメント.py:
@registry.register_document
class SubmissionDocument(Document)
rawtext = fields.TextField(attr="type_to_string")
def prepare_rawtext(self, instance):
# self.rawtext = None
# instance.rawtext = "test"
return instance.rawtext
...
tasks.py (サブミッション モデルの post_save シグナルで呼び出されます):
@shared_task
def process_ocr(my_uuid)
result = "test" # will ultimately be OCR'd text
instance = Submission.objects.get(my_uuid=my_uuid)
instance.rawtext = result
instance.save()
更新 2 (実用的なソリューション):
models.py クラスの提出 (models.Model):
@property
def rawtext(self):
if getattr(self, '_rawtext_local_change', False):
return self._rawtext
if not self.pk:
return None
from .documents import SubmissionDocument
try:
return SubmissionDocument.get(id=self.pk)._rawtext
except:
return None
@rawtext.setter
def rawtext(self, value):
self._rawtext_local_change = True
self._rawtext = value
ドキュメント.py
@registry.register_document
class SubmissionDocument(Document):
rawtext = fields.TextField()
def prepare_rawtext(self, instance):
return instance.rawtext
タスク.py
@shared_task
def process_ocr(my_uuid)
result = "test" # will ultimately be OCR'd text
# note that you must do a save on property fields, can't do an update
instance = Submission.objects.get(my_uuid=my_uuid)
instance.rawtext = result
instance.save()