ZomboDB рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкрд░ Django ORM рдХрд╛ рдЕрдиреБрдХреВрд▓рди

рдЕрдХреНрд╕рд░ рдЬрдм Django рдФрд░ PostgreSQL рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ , рддреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдФрд░ рдЕрдЧрд░ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП hstore рдпрд╛ PostGIS (GeoDjango рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж) рдХреЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рдХрд╛рдлреА рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рддреЛ рджреБрд░реНрд▓рдн рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд╕рд╛рде - рдЬреИрд╕реЗ pgRout, ZomboDB, рдЖрджрд┐ - рдЖрдкрдХреЛ рдпрд╛ рддреЛ RawSQL рдореЗрдВ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ рдпрд╛ DjM ORM рдХреЛ рдХрд╕реНрдЯрдорд╛рдЗрдЬрд╝ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВрдиреЗ рдЬреЛ рдкреНрд░рд╕реНрддрд╛рд╡ рд░рдЦрд╛ рд╣реИ, рд╡рд╣ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ ZomboDB рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреА рд╢реБрд░реБрдЖрдд рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХрд░рдирд╛ рд╣реИ ред рдФрд░ рдЙрд╕реА рд╕рдордп, рдЖрдЗрдП рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рдЖрдк ZomboDB рдХреЛ рдПрдХ Django рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдХреИрд╕реЗ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред


PostgreSQL рдХреА рдЕрдкрдиреА рдкреВрд░реНрдг-рдкрд╛рда рдЦреЛрдЬ рд╣реИ рдФрд░ рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдирд╡реАрдирддрдо рдорд╛рдирджрдВрдб, рдмрд╣реБрдд рдЬрд▓реНрджреАред рд▓реЗрдХрд┐рди рдЦреЛрдЬ рдореЗрдВ рдЗрд╕рдХреА рдХреНрд╖рдорддрд╛ рдЕрднреА рднреА рд╡рд╛рдВрдЫрд┐рдд рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдХреБрдЫ рдЫреЛрдбрд╝ рджреЗрддреА рд╣реИред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд▓реНрдпреВрд╕рд┐рдиреЗ-рдЖрдзрд╛рд░рд┐рдд рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреЗ рдмрд┐рдирд╛ - ElasticSearch, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП - рддрдВрдЧ рд╣реИред ElasticSearch рдХреЗ рдЕрдВрджрд░ рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдбреЗрдЯрд╛рдмреЗрд╕ рд╣реИ, рдЬреЛ рдЦреЛрдЬ рдХрд╛ рд╕рдВрдЪрд╛рд▓рди рдХрд░рддрд╛ рд╣реИред рдлрд┐рд▓рд╣рд╛рд▓ рдореБрдЦреНрдп рд╕рдорд╛рдзрд╛рди рд╕рд┐рдЧреНрдирд▓ рдпрд╛ рдореИрдиреБрдЕрд▓ рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ PostgreSQL рдФрд░ ElasticSearch рдХреЗ рдмреАрдЪ рдбреЗрдЯрд╛ рд╕реНрдерд┐рд░рддрд╛ рдХрд╛ рдореИрдиреБрдЕрд▓ рдирд┐рдпрдВрддреНрд░рдг рд╣реИред


ZomboDB рдПрдХ рдРрд╕рд╛ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╣реИ, рдЬреЛ рдЕрдкрдиреЗ рд╣реА рдкреНрд░рдХрд╛рд░ рдХреЗ рдЗрдВрдбреЗрдХреНрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рддрд╛рд▓рд┐рдХрд╛ рдореВрд▓реНрдп рдХреЛ ElasticSearch рдХреЗ рд▓рд┐рдП рдПрдХ рдкреЙрдЗрдВрдЯрд░ рдореЗрдВ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ, рдЬреЛ SQL рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд░реВрдк рдореЗрдВ ElasticSearch DSL рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреВрд░реНрдг-рдкрд╛рда рддрд╛рд▓рд┐рдХрд╛ рдЦреЛрдЬреЛрдВ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред


рд▓реЗрдЦрди рдХреЗ рд╕рдордп, рдПрдХ рдиреЗрдЯрд╡рд░реНрдХ рдЦреЛрдЬ рдиреЗ рдХреЛрдИ рдкрд░рд┐рдгрд╛рдо рдирд╣реАрдВ рджрд┐рдпрд╛ред рдХреЗрд╡рд▓ ZomboDB рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ Habr├й рдкрд░ рд▓реЗрдЦреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ ред ZomboDB рдФрд░ Django рдХреЛ рдПрдХреАрдХреГрдд рдХрд░рдиреЗ рдкрд░ рдХреЛрдИ рд▓реЗрдЦ рдирд╣реАрдВ рд╣реИред


ZomboDB рд╡рд┐рд╡рд░рдг рдореЗрдВ рдХрд╣рд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдПрд▓рд┐рд╕реНрдЯрд┐рдХреНрд╕ рдХреЛ рдХреЙрд▓ рд░рд┐рд╕реНрдЯрдлреБрд▓ рдПрдкреАрдЖрдИ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдкреНрд░рджрд░реНрд╢рди рд╕рдВрджреЗрд╣ рдореЗрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдм рд╣рдо рдЗрд╕ рдкрд░ рд╕реНрдкрд░реНрд╢ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗред рдбреЗрдЯрд╛ рд╣рд╛рдирд┐ рдХреЗ рдмрд┐рдирд╛ ZomboDB рдХреЗ рд╕рд╣реА рд╣рдЯрд╛рдиреЗ рдХреЗ рдореБрджреНрджреЗ рднреАред


рдЕрдЧрд▓рд╛, рд╣рдо рдбреЙрдХрдЯрд░ рдореЗрдВ рд╕рднреА рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдПрдХ рдЫреЛрдЯреЗ рдбреЙрдХрдЯрд░-рдХрдореНрдкреЛрдЬ рдлрд╛рдЗрд▓ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░реЗрдВрдЧреЗ


рдбреЛрдХрд░-compose.yaml
version: '3' services: postgres: build: docker/postgres environment: - POSTGRES_USER=django - POSTGRES_PASSWORD=123456 - POSTGRES_DB=zombodb - PGDATA=/home/postgresql/data ports: - 5432:5432 # sudo sysctl -w vm.max_map_count=262144 elasticsearch: image: elasticsearch:6.5.4 environment: - cluster.name=zombodb - bootstrap.memory_lock=true - ES_JAVA_OPTS=-Xms512m -Xmx512m ulimits: memlock: soft: -1 hard: -1 ports: - 9200:9200 django: build: docker/python command: python3 manage.py runserver 0.0.0.0:8000 volumes: - ./:/home/ ports: - 8000:8000 depends_on: - postgres - elasticsearch 

ZomboDB рдХрд╛ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг Postgres рдХреЗ рдЕрдзрд┐рдХрддрдо 10 рд╡реЗрдВ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрднрд░рддрд╛ рд╕реЗ рдХрд░реНрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ (рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ ElasticSearch рдореЗрдВ рдкреНрд░рд╢реНрди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП)ред


 FROM postgres:10 WORKDIR /home/ RUN apt-get -y update && apt-get -y install curl ADD https://www.zombodb.com/releases/v10-1.0.3/zombodb_jessie_pg10-10-1.0.3_amd64.deb ./ RUN dpkg -i zombodb_jessie_pg10-10-1.0.3_amd64.deb RUN rm zombodb_jessie_pg10-10-1.0.3_amd64.deb RUN apt-get -y clean 

Django рдХреЗ рд▓рд┐рдП рдХрдВрдЯреЗрдирд░ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИред рдЗрд╕рдореЗрдВ рд╣рдо рдХреЗрд╡рд▓ Django рдФрд░ psycopg2 рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдбрд╛рд▓реЗрдВрдЧреЗред


 FROM python:stretch WORKDIR /home/ RUN pip3 install --no-cache-dir django psycopg2-binary 

рд▓рд┐рдирдХреНрд╕ рдкрд░ рдЗрд▓рд╛рд╕реНрдЯрд┐рдХрд╕рд░реНрдЪ vm.max_map_count рдХреА рдореВрд▓ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╕реЗ рд╢реБрд░реВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдереЛрдбрд╝рд╛ рдмрдврд╝рд╛рдирд╛ рд╣реЛрдЧрд╛ (рдЬреЛ рдбреЙрдХрдЯрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕реЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рдирд╛ рдЬрд╛рдирддрд╛ рд╣реИ - рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рд▓рд┐рдЦреЗрдВ)ред


 sudo sysctl -w vm.max_map_count=262144 

рддреЛ, рдкрд░реАрдХреНрд╖рдг рд╡рд╛рддрд╛рд╡рд░рдг рддреИрдпрд╛рд░ рд╣реИред рдЖрдк Django рдкрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкрд░ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдореИрдВ рдЗрд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд╣реАрдВ рджреЗ рд╕рдХрддрд╛; рдЬреЛ рд▓реЛрдЧ рдЗрд╕реЗ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╡реЗ рдЗрд╕реЗ GitLab рдХреЗ рднрдВрдбрд╛рд░ рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдореИрдВ рдХреЗрд╡рд▓ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдВрджреБрдУрдВ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдиреНрджреНрд░рд┐рдд рдХрд░реВрдВрдЧрд╛ред


рдкрд╣рд▓реА рдЪреАрдЬ рдЬреЛ рд╣рдореЗрдВ рдХрд░рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ рд╡рд╣ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдХреНрдпреВрдПрд▓ рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╝реЛрдореНрдмреЛрдмреАрдбреА рдореЗрдВ рдкреНрд▓рдЧ рд╣реИред рдЖрдк рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ SQL CREATE EXTENSION zombodb; рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЛ рд╕рдХреНрд╖рдо рдХрд░ CREATE EXTENSION zombodb; ред рдЖрдк рдЗрд╕рдХреЗ рд▓рд┐рдП рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдЬ рдХрдВрдЯреЗрдирд░ рдореЗрдВ docker-entrypoint-initdb.d рд╣реБрдХ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЬрдм рд╕реЗ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Django рд╣реИ, рддрдм рд╣рдо рдЙрд╕рдХреЗ рд░рд╛рд╕реНрддреЗ рдкрд░ рдЬрд╛рдПрдВрдЧреЗред
рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдФрд░ рдкрд╣рд▓реЗ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, рдЗрд╕рдореЗрдВ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХрдиреЗрдХреНрд╢рди рдЬреЛрдбрд╝реЗрдВред


 from django.db import migrations, models from django.contrib.postgres.operations import CreateExtension class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ CreateExtension('zombodb'), ] 

рджреВрд╕рд░реЗ, рд╣рдореЗрдВ рдПрдХ рдореЙрдбрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рдкрд░реАрдХреНрд╖рдг рдкреИрдЯрд░реНрди рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдЧрд╛ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рдлрд╝реАрд▓реНрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ zdb.fulltext рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЕрдЪреНрдЫрд╛, рдЪрд▓реЛ рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рд▓рд┐рдЦреЛ ред рдЪреВрдВрдХрд┐ django рдХреЗ рд▓рд┐рдП рдпрд╣ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рджреЗрд╢реА рдкреЛрд╕реНрдЯрдЧреНрд░реИрдХреНрд╕реНрд▓ рдЯреЗрдХреНрд╕реНрдЯ рдХреЗ рд╕рдорд╛рди рд╣реИ, рдЬрдм рд╣рдо рдЕрдкрдирд╛ рдХреНрд╖реЗрддреНрд░ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдореЙрдбрд▓ рд╕реЗ рдЕрдкрдирд╛ рд╡рд░реНрдЧ рд╡рд╛рд░ рдХрд░реЗрдВрдЧреЗред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рджреЛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЪреАрдЬреЗрдВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ: рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдкрд░ рдмреАрдЯреАрдЖрд░рдИ рд╕реВрдЪрдХрд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЛ рдмрдВрдж рдХрд░реЗрдВ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП рдмреИрдХрдПрдВрдб рдХреЛ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдХрд░реЗрдВред рдЕрдВрддрд┐рдо рдкрд░рд┐рдгрд╛рдо рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:


 class ZomboField(models.TextField): description = "Alias for Zombodb field" def __init__(self, *args, **kwargs): kwargs['db_index'] = False super().__init__(*args, **kwargs) def db_type(self, connection): databases = [ 'django.db.backends.postgresql_psycopg2', 'django.db.backends.postgis' ] if connection.settings_dict['ENGINE'] in databases: return 'zdb.fulltext' else: raise TypeError('This database not support') 

рддреАрд╕рд░рд╛, ZomboDB рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрддрд╛рдПрдВ рдЬрд╣рд╛рдВ рд╣рдорд╛рд░реА ElasticSearch рдЦреЛрдЬ рдХрд░рдиреА рд╣реИред рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╣реА, ZomboDB рд╕реЗ рдПрдХ рдХрд╕реНрдЯрдо рдЗрдВрдбреЗрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЗрд╕ рдЙрджреНрджреЗрд╢реНрдп рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдпрджрд┐ рдкрддрд╛ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ред
Django рдРрдк_рдореЙрдбрд▓ рдкреИрдЯрд░реНрди рдХреЗ рдЕрдиреБрд╕рд╛рд░ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХрд╛ рдирд╛рдо рджреЗрддрд╛ рд╣реИ: рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдореБрдЦреНрдп рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдореЙрдбрд▓ рд▓реЗрдЦ рд╣реИред рдЗрд▓рд╛рд╕реНрдЯрд┐рдХреНрд╕ рдЦреЛрдЬ рдбреАрдПрдирдПрд╕ рдирд╛рдо рд╣реИ рдЬреЛ рдбреЙрдХрдЯрд░ рдХрдВрдЯреЗрдирд░ рдирд╛рдо рд╕реЗ рдЕрд╕рд╛рдЗрди рдХрд░рддрд╛ рд╣реИред
SQL рдореЗрдВ, рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 CREATE INDEX idx_main_article ON main_article USING zombodb ((main_article.*)) WITH (url='elasticsearch:9200/'); 

Django рдореЗрдВ, рд╣рдореЗрдВ рдПрдХ рдХрд╕реНрдЯрдо рдЗрдВрдбреЗрдХреНрд╕ рдмрдирд╛рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕реВрдЪрдХрд╛рдВрдХ рдЕрднреА рддрдХ рдмрд╣реБрдд рд▓рдЪреАрд▓реЗ рдирд╣реАрдВ рд╣реИрдВ: рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдЬреЛрдореНрдмреЛрдбрдм рдЗрдВрдбреЗрдХреНрд╕ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреЙрд▓рдо рдХреЛ рдЗрдВрдЧрд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдВрдкреВрд░реНрдг рддрд╛рд▓рд┐рдХрд╛ ред Django рдореЗрдВ, рдПрдХ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рдПрдХ рдЕрдирд┐рд╡рд╛рд░реНрдп рдлрд╝реАрд▓реНрдб рд╕рдВрджрд░реНрдн рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ statement.parts['columns'] ((main_article.*)) рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдирд┐рд░реНрдорд╛рдг рдФрд░ ((main_article.*)) рддрд░реАрдХреЛрдВ рдХреЛ рдЕрднреА рднреА рдлрд╝реАрд▓реНрдб рдмрдирд╛рддреЗ рд╕рдордп рдлрд╝реАрд▓реНрдб рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рд╣рдореЗрдВ рдкреИрд░рд╛рдореЗрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдкреИрд░рд╛рдореАрдЯрд░ рднреА рдкрд╛рд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред get_with_params рдУрд╡рд░рд░рд╛рдЗрдб рдХреНрдпреЛрдВ рдХрд░реЗрдВ, get_with_params рдФрд░ get_with_params ред
рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдбрд┐рдЬрд╛рдЗрди рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдХрд▓рд╛ред рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рдмрд┐рдирд╛ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рд▓рд╛рдЧреВ рдФрд░ рд░рджреНрдж рдХрд░ рджрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред


 class ZomboIndex(models.Index): def __init__(self, *, url=None, **kwargs): self.url = url super().__init__(**kwargs) def create_sql(self, model, schema_editor, using=''): statement = super().create_sql(model, schema_editor, using=' USING zombodb') statement.parts['columns'] = '(%s.*)' % model._meta.db_table with_params = self.get_with_params() if with_params: statement.parts['extra'] = " WITH (%s) %s" % ( ', '.join(with_params), statement.parts['extra'], ) print(statement) return statement def deconstruct(self): path, args, kwargs = super().deconstruct() if self.url is not None: kwargs['url'] = self.url return path, args, kwargs def get_with_params(self): with_params = [] if self.url: with_params.append("url='%s'" % self.url) return with_params 

рдЬрд┐рди рд▓реЛрдЧреЛрдВ рдХреЛ рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд╕рдВрдж рдирд╣реАрдВ рд╣реИ, рд╡реЗ рд╕реАрдзреЗ рдПрдХ рдЗрдВрдбреЗрдХреНрд╕ рдЬреЛрдбрд╝рдХрд░ RunSQL рд╕реЗ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдкрдХреЛ рдмрд╕ рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рдирд╛рдо рдХрд╛ рдЯреНрд░реИрдХ рд░рдЦрдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЕрдкрдиреЗ рдЖрдк рдХреЛ рдЕрдиреБрдХреНрд░рдорд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред


 migrations.RunSQL( sql = ( "CREATE INDEX idx_main_article " "ON main_article " "USING zombodb ((main_article.*)) " "WITH (url='elasticsearch:9200/');" ), reverse_sql='DROP INDEX idx_main_article' ) 

рдкрд░рд┐рдгрд╛рдо рдПрдХ рдРрд╕рд╛ рдореЙрдбрд▓ рд╣реИред ZomboField TextField рдХреЗ рд╕рдорд╛рди рд╣реА рддрд░реНрдХ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде - index_db рдХреБрдЫ рднреА рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдареАрдХ рдЙрд╕реА рддрд░рд╣ рдЬреИрд╕реЗ рдлрд╝реАрд▓реНрдб ZomboIndex рдореЗрдВ рд╡рд┐рд╢реЗрд╖рддрд╛ рд╣реИред


 class Article(models.Model): text = ZomboField() class Meta: indexes = [ ZomboIndex(url='elasticsearch:9200/', name='zombo_idx', fields=['text']) ] 

рдЕрдВрдд рдореЗрдВ, рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдиреА рдЪрд╛рд╣рд┐рдП:


 from django.db import migrations, models from django.contrib.postgres.operations import CreateExtension import main.models class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ CreateExtension('zombodb'), migrations.CreateModel( name='Article', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('text', main.models.ZomboField()), ], ), migrations.AddIndex( model_name='article', index=main.models.ZomboIndex(fields=['text'], name='zombo_idx', url='elasticsearch:9200/'), ) ] 

рд░реБрдЪрд┐ рд░рдЦрдиреЗ рд╡рд╛рд▓реЛрдВ рдХреЗ рд▓рд┐рдП, рдореИрдВ Django ORM рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рд╡рд╛рд▓реЗ SQL рдХреЛ рд╕рдВрд▓рдЧреНрди рдХрд░рддрд╛ рд╣реВрдВ (рдЖрдк sqlmigrate рдорд╛рдзреНрдпрдо рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ, рдпрд╛ рдЦрд╛рддреЗ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддреЗ рд╣реБрдП: sudo docker-compose exec django python3 manage.py sqlmigrate main 0001 )


 BEGIN; -- -- Creates extension zombodb -- CREATE EXTENSION IF NOT EXISTS "zombodb"; -- -- Create model Article -- CREATE TABLE "main_article" ("id" serial NOT NULL PRIMARY KEY, "text" zdb.fulltext NOT NULL); -- -- Create index zombo_idx on field(s) text of model article -- CREATE INDEX "zombo_idx" ON "main_article" USING zombodb ((main_article.*)) WITH (url='elasticsearch:9200/') ; COMMIT; 

рдЗрд╕рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдореЙрдбрд▓ рд╣реИред рдпрд╣ рдЕрдм рдлрд┐рд▓реНрдЯрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХ рдЦреЛрдЬ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЕрдкрдиреЗ рд▓реБрдХрдЕрдк рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдВред


 @ZomboField.register_lookup class ZomboSearch(models.Lookup): lookup_name = 'zombo_search' def as_sql(self, compiler, connection): lhs, lhs_params = self.process_lhs(compiler, connection) rhs, rhs_params = self.process_rhs(compiler, connection) params = lhs_params + rhs_params return "%s ==> %s" % (lhs.split('.')[0], rhs), params 

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЦреЛрдЬ рдЗрд╕ рддрд░рд╣ рд╣реЛрдЧреА:


 Article.objects.filter(text__zombo_search='(call OR box)') 

рд▓реЗрдХрд┐рди рдЖрдорддреМрд░ рдкрд░ рдПрдХ рдЦреЛрдЬ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИред рдЗрд╕рдореЗрдВ рдкрд░рд┐рдгрд╛рдо рдХреА рд░реИрдВрдХрд┐рдВрдЧ рдФрд░ рдкрд╛рдП рдЧрдП рд╢рдмреНрджреЛрдВ рдХреЛ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд░рдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
рдареАрдХ рд╣реИ, рд░реИрдВрдХрд┐рдВрдЧ рдмрд╣реБрдд рд╕реАрдзрд╛ рд╣реИред рд╣рдо рдЕрдкрдирд╛ рдХрд╛рд░реНрдп рд▓рд┐рдЦрддреЗ рд╣реИрдВ:


 from django.db.models import FloatField, Func class ZomboScore(Func): lookup_name = 'score' function = 'zdb.score' template = "%(function)s(ctid)" arity = 0 @property def output_field(self): return FloatField() 

рдЕрдм рдЖрдк рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ рдХрд╛рдлреА рдЬрдЯрд┐рд▓ рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


 scores = (Article.objects .filter(text__zombo_search='delete') .annotate(score=ZomboScore()) .values_list(F('score')) .order_by('-score')) 

рдкрд░рд┐рдгрд╛рдо рдХреЛ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд░рдирд╛ (рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд░рдирд╛) рдХреБрдЫ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реЛ рдЧрдпрд╛, рдпрд╣ рд╕реБрдВрджрд░ рддрд░реАрдХреЗ рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред Django psycopg2 рдмреИрдХреЗрдВрдб рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ _ рдХреЛ _ рд░реВрдкрд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред _ ред рдпрджрд┐ text рдерд╛, рддреЛ "main_article"."text" , рдЬрд┐рд╕реЗ ZomboDB рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рд╕реНрд╡реАрдХрд╛рд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рд╕реНрддрдВрдн рдкрджрдирд╛рдо рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реНрддрдВрдн рдХрд╛ рдкрд╛рдареНрдп рдирд╛рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдпрд╣рд╛рдБ RawSQL рдмрдЪрд╛рд╡ рдХреЗ рд▓рд┐рдП рдЖрддрд╛ рд╣реИред


 from django.db.models.expressions import RawSQL highlighted = (Article.objects .filter(text__zombo_search='delete') .values(highlight_text=RawSQL("zdb.highlight(ctid, %s)", ('text',)))) 

рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рдкреВрд░реНрдг рд╕рдВрд╕реНрдХрд░рдг рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред рд▓реЗрдЦ рдХреЗ рд╕рднреА рдЙрджрд╛рд╣рд░рдг рдкрд░реАрдХреНрд╖рдг рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд╣рд╛рдВ рд▓рд┐рдЦреЗ рдЧрдП рд╣реИрдВред рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдХреЗ рд▓рд┐рдП рдпрд╣ рд▓реЗрдЦ рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛ рдФрд░ рдЖрдкрдХреЛ рд╕рдВрдХреЗрддреЛрдВ рдкрд░ рдПрдХ рд╕рд╛рдЗрдХрд┐рд▓ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрддреНрд╕рд╛рд╣рд┐рдд рдирд╣реАрдВ рдХрд░реЗрдЧрд╛, рдЬрд┐рд╕рдореЗрдВ рд╕реНрд╡рдпрдВ рдХреЛ рд╕рднреА рд╕реБрд╕рдВрдЧрддрддрд╛ рдХреЛ рд╢реВрдЯ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реЛрдЧреА, рдФрд░ рдУрдЖрд░рдПрдо рдХреЗ рд╕рднреА рд╕рдХрд╛рд░рд╛рддреНрдордХ рдкрд╣рд▓реБрдУрдВ рдХреЛ рдЦреЛрдП рдмрд┐рдирд╛ рдПрдХ рддреИрдпрд╛рд░ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдкрд░рд┐рд╡рд░реНрдзрди рдФрд░ рд╕реБрдзрд╛рд░ рдХрд╛ рднреА рд╕реНрд╡рд╛рдЧрдд рд╣реИред


UPD: django-zombodb рд▓рд╛рдЗрдмреНрд░реЗрд░реА рджрд┐рдЦрд╛рдИ рджреА рд╣реИ

Source: https://habr.com/ru/post/hi442512/


All Articles