之前用Elasticsearch进行数据查询的方式很少,最近在进行Elasticsearch相关的查询操作。这里记录一下如何使用python语言,将PostgreSQL数据库中的数据同步到Elasticsearch中,方便进行高效的查询。

Elasticsearch与PostgreSQL对比

Elasticsearch与PostgreSQL是两种不同类型的数据库,它们各自有其特点和适用场景。以下是它们的一些对比:

  • 数据存储方式:
  • Elasticsearch:Elasticsearch是一个基于Lucene的全文搜索引擎,它将数据索引以便快速搜索。它不是传统的关系数据库,不支持ACID事务。
  • PostgreSQL:PostgreSQL是一个关系型数据库管理系统(RDBMS),遵循ACID模型,支持复杂的SQL查询和事务。
  • 数据结构和类型:
  • Elasticsearch:Elasticsearch使用JSON文档,但它有自己的数据结构,如字段映射和内部索引。
  • PostgreSQL:PostgreSQL使用SQL表来存储数据,并且可以定义复杂的数据类型和关系。
  • 性能和可扩展性:
  • Elasticsearch:Elasticsearch通过分布式架构提供极致的可扩展性,能够处理大量的数据。
  • PostgreSQL:PostgreSQL也支持高可扩展性,通过分片和复制可以扩展数据库。
  • 查询和分析能力:
  • Elasticsearch:Elasticsearch专注于全文搜索和分析,拥有强大的全文搜索和聚合功能。
  • PostgreSQL:PostgreSQL拥有强大的SQL查询和复杂分析功能,包括复杂的连接、窗口函数和聚合查询。
  • 成熟度和社区支持:
  • Elasticsearch:Elasticsearch拥有成熟的生态系统和广泛的社区支持。
  • PostgreSQL:PostgreSQL有着成熟的生态系统和广泛支持,并且在数据一致性和安全性方面有着丰富的经验。
  • 定价和许可:
  • Elasticsearch:Elasticsearch是开源免费的,但需要自己维护。
  • PostgreSQL:PostgreSQL有开源免费版本,也有商业版本,需要根据需求选择。

选择哪种数据库取决于具体需求,如数据类型、查询要求、可扩展性、成本等。在某些情况下,可以将Elasticsearch与PostgreSQL结合使用,以利用它们各自的优势。

同步数代码

# pip install elasticsearch7.10.1
from elasticsearch import Elasticsearch, helpers
import psycopg2
import json

from datetime import datetime

# 连接PostgreSQL数据库
conn = psycopg2.connect(
    dbname="postgres",
    user="postgres",
    password="postgresql",
    host="192.168.1.2"
)
cur = conn.cursor()
# 从数据库查询数据
cur.execute("SELECT arealevel,coid,env,qhdm,qhmc,null as type ,to_char(updatetime,'yyyy-MM-dd HH:mm:ss') as "
            "updatetime FROM sys_area limit 1000000")
rows = cur.fetchall()


def delete_index(es, index_name):
    """
    删除索引
    :param es: Elasticsearch对象
    :param index_name: 索引名称
    :return:
    """
    if es.indices.exists(index=index_name):
        # 删除索引
        response = es.indices.delete(index=index_name)
        print(response)


def create_index(es, index_name, body):
    """
    创建索引
    :param es: Elasticsearch对象
    :param index_name: 索引名称
    :return:
    """
    if not es.indices.exists(index=index_name):
        # 创建索引
        index_name = index_name

        response = es.indices.create(index=index_name, body=body)
        print(response)


if __name__ == '__main__':
    actions = []
    v_lens = 0
    # 连接到Elasticsearch
    es = Elasticsearch("http://192.168.1.2:9200")
    delete_index(es, "sys_area")
    body = {
        "settings": {
            "number_of_shards": 3,
            "number_of_replicas": 1
        },
        "mappings": {
            "properties": {
                "arealevel": {
                    "type": "text", "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "coid": {
                    "type": "text", "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "env": {
                    "type": "text", "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "qhdm": {
                    "type": "text", "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }

                },
                "qhmc": {
                    "type": "text", "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "type": {
                    "type": "text", "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "updatetime": {
                    "type": "date",
                    "format": "yyyy-MM-dd HH:mm:ss"
                }
            }
        }
    }

    create_index(es, "sys_area", body)
    for row in rows:
        action = {
            "_index": "sys_area",
            "_id": row[3],  # 假设第一列是ID
            "_source": {
                "arealevel": row[0],
                "coid": row[1],
                "env": row[2],
                "qhdm": row[3],
                "qhmc": row[4],
                "type": row[5],
                "updatetime": row[6]
            }
        }
        actions.append(action)
        if len(actions) == 1000:
            v_lens += len(actions)
            print('========已处理1000条数据,开始发送es=======')
            helpers.bulk(es, actions)
            del actions[0:len(actions)]

    # 使用helpers库进行数据同步
    v_lens += len(actions)
    if v_lens > 0:
        print('========开始发送最后' + str(len(actions)) + '条数据到es=======')
        helpers.bulk(es, actions)
    print('========合计发送' + str(v_lens) + '条数据到es=======')

    # 关闭数据库连接
    cur.close()
    conn.close()