مستندات n8n
74+ نود
🐘

پستگرس

PostgreSQL

اتصال به PostgreSQL، اجرای SQL پیشرفته با JSON و Full-text Search

دیتابیس
متوسط
۰ بازدید
n8n 1.0+

نمای کلی

نود PostgreSQL یکی از نودهای کلیدی n8n برای کار با دیتابیس‌های پیشرفته است.

قابلیت‌های کلیدی:

  • اتصال به PostgreSQL با SSL/TLS
  • اجرای کوئری‌های SQL پیشرفته
  • پشتیبانی کامل از JSONB (ذخیره و جستجوی JSON)
  • Full-text Search فارسی و انگلیسی
  • پشتیبانی از Array و Composite Types
  • پشتیبانی از RETURNING clause
  • Window Functions و CTE
  • SSH Tunnel برای اتصال امن

کاربردها:

  • سیستم‌های بزرگ با داده‌های پیچیده
  • ذخیره و جستجوی داده‌های JSON
  • جستجوی متنی پیشرفته
  • سیستم‌های مالی (ACID Compliance)
  • GIS و داده‌های مکانی (PostGIS)
  • آنالیز داده و گزارش‌گیری پیشرفته
  • Real-time با LISTEN/NOTIFY

مزایای PostgreSQL نسبت به MySQL:

  • پشتیبانی بهتر از JSON (JSONB)
  • Full-text Search قدرتمندتر
  • Window Functions پیشرفته‌تر
  • ACID Compliance بهتر
  • Extensible (پسوندهای سفارشی)
  • دقت بالاتر در محاسبات عددی

احراز هویت

احراز هویت PostgreSQL

روش 1: اتصال مستقیم

  1. 1در n8n به بخش Credentials بروید
  2. 2PostgreSQL را انتخاب کنید
  3. 3اطلاعات زیر را وارد کنید:
code
Host: localhost یا IP سرور
Port: 5432 (پیش‌فرض)
Database: نام دیتابیس
User: نام کاربری
Password: رمز عبور
SSL: disable / require / verify-full

روش 2: Connection String

code
postgresql://username:password@host:5432/database?sslmode=require

روش 3: SSL Connection (برای Production)

  1. 1SSL Mode: require یا verify-full
  2. 2CA Certificate: محتوای ca-cert.pem
  3. 3Client Certificate: (اختیاری)
  4. 4Client Key: (اختیاری)

روش 4: SSH Tunnel

برای سرورهایی که دسترسی مستقیم ندارند:

  1. 1SSH Host و Port
  2. 2SSH User و Password/Key
  3. 3PostgreSQL از طریق tunnel متصل می‌شود

ایجاد کاربر اختصاصی:

sql
-- ایجاد کاربر
CREATE USER n8n_user WITH PASSWORD 'StrongPassword123!';

-- ایجاد دیتابیس (اختیاری)
CREATE DATABASE my_app OWNER n8n_user;

-- دادن دسترسی روی Schema
GRANT USAGE ON SCHEMA public TO n8n_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO n8n_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO n8n_user;

-- دسترسی خودکار برای جداول آینده
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO n8n_user;

تنظیمات pg_hba.conf (اتصال ریموت):

code
# /etc/postgresql/15/main/pg_hba.conf
# اجازه اتصال از IP مشخص
host    my_app    n8n_user    192.168.1.0/24    scram-sha-256

نکات امنیتی:

  • از scram-sha-256 به جای md5 استفاده کنید
  • دسترسی کاربر را محدود کنید (GRANT فقط لازم‌ها)
  • SSL را حتماً فعال کنید
  • از SSH Tunnel برای اتصال‌های ریموت استفاده کنید

عملیات‌های موجود

1

executeQuery

اجرای هر نوع کوئری SQL دلخواه

2

insert

درج رکورد جدید با RETURNING

3

update

به‌روزرسانی با شرط و RETURNING

4

delete

حذف رکوردها با شرط

کاربردهای متداول

1. ذخیره داده JSON در JSONB

ذخیره داده‌های نیمه‌ساختاریافته:

code
Webhook (دریافت سفارش)
  → PostgreSQL (Execute Query)
    INSERT INTO orders (customer_id, details, metadata)
    VALUES (
      {{$json.customer_id}},
      '{{JSON.stringify($json.items)}}'::jsonb,
      '{"source": "website", "ip": "{{$json.ip}}"}'::jsonb
    )
    RETURNING id, created_at

2. جستجوی JSON

جستجو در فیلدهای JSONB:

sql
-- جستجو در JSON
SELECT * FROM orders
WHERE details->>'status' = 'paid'
AND (metadata->>'amount')::int > 100000

-- جستجوی آرایه در JSON
SELECT * FROM products
WHERE tags ? 'electronics'

-- جستجوی تودرتو
SELECT * FROM users
WHERE profile->'address'->>'city' = 'Tehran'

3. Full-text Search

جستجوی متنی پیشرفته:

code
Webhook (جستجو)
  → PostgreSQL (Execute Query)
    SELECT id, title, description,
      ts_rank(search_vector, query) as rank
    FROM articles,
      to_tsquery('simple', '{{$json.keyword}}') query
    WHERE search_vector @@ query
    ORDER BY rank DESC
    LIMIT 20

4. سیستم لاگ‌گیری

ذخیره لاگ‌های فعالیت:

code
هر رویداد → PostgreSQL (Insert)
  - Table: activity_logs
  - Columns: user_id, action, details (JSONB), ip_address, created_at

-- بعداً گزارش:
SELECT action, COUNT(*) as count,
  DATE(created_at) as date
FROM activity_logs
WHERE created_at >= NOW() - INTERVAL '7 days'
GROUP BY action, DATE(created_at)
ORDER BY date DESC, count DESC

5. UPSERT (Insert or Update)

درج یا به‌روزرسانی:

sql
INSERT INTO daily_stats (date, page, views)
VALUES (CURRENT_DATE, '{{$json.page}}', 1)
ON CONFLICT (date, page)
DO UPDATE SET views = daily_stats.views + 1
RETURNING *

6. CTE (Common Table Expressions)

کوئری‌های پیچیده با WITH:

sql
WITH monthly_sales AS (
  SELECT
    DATE_TRUNC('month', created_at) as month,
    SUM(amount) as total,
    COUNT(*) as orders
  FROM orders
  WHERE created_at >= NOW() - INTERVAL '12 months'
  GROUP BY month
),
growth AS (
  SELECT *,
    LAG(total) OVER (ORDER BY month) as prev_month,
    ROUND((total - LAG(total) OVER (ORDER BY month))
      / LAG(total) OVER (ORDER BY month) * 100, 1) as growth_pct
  FROM monthly_sales
)
SELECT * FROM growth ORDER BY month DESC

7. Window Functions

محاسبات پیشرفته:

sql
SELECT
  name,
  department,
  salary,
  RANK() OVER (PARTITION BY department ORDER BY salary DESC) as dept_rank,
  salary - AVG(salary) OVER (PARTITION BY department) as diff_from_avg,
  SUM(salary) OVER (ORDER BY salary DESC) as running_total
FROM employees

8. سیستم اعلان با LISTEN/NOTIFY

اعلان تغییرات Real-time:

sql
-- ایجاد تریگر
CREATE OR REPLACE FUNCTION notify_new_order()
RETURNS TRIGGER AS $$
BEGIN
  PERFORM pg_notify('new_order', row_to_json(NEW)::text);
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER order_created
AFTER INSERT ON orders
FOR EACH ROW EXECUTE FUNCTION notify_new_order();

9. بک‌آپ و Export

خروجی CSV:

sql
COPY (
  SELECT id, name, email, phone
  FROM customers
  WHERE active = true
) TO '/tmp/customers.csv'
WITH CSV HEADER

10. گزارش داشبورد

آمار کلی برای داشبورد:

code
Schedule (هر 5 دقیقه) → PostgreSQL
  SELECT
    (SELECT COUNT(*) FROM users WHERE active) as total_users,
    (SELECT COUNT(*) FROM orders WHERE DATE(created_at) = CURRENT_DATE) as today_orders,
    (SELECT COALESCE(SUM(amount),0) FROM orders WHERE DATE(created_at) = CURRENT_DATE) as today_revenue,
    (SELECT COUNT(*) FROM tickets WHERE status = 'open') as open_tickets
  → Set (فرمت فارسی) → Telegram (ارسال)

نکات حرفه‌ای

نکات حرفه‌ای

  1. 1RETURNING: بعد از INSERT/UPDATE نتیجه بگیرید:
sql
INSERT INTO users (name, email)
   VALUES ('Ali', 'ali@test.com')
   RETURNING id, created_at;
  1. 1JSONB Operators: عملگرهای JSON:
sql
-- دسترسی به فیلد (text)
   data->>'name'

   -- دسترسی تودرتو (json)
   data->'address'->'city'

   -- بررسی وجود کلید
   data ? 'email'

   -- بروزرسانی JSON
   data || '{"status": "active"}'::jsonb

   -- حذف کلید
   data - 'temp_field'
  1. 1Array Operations:
sql
-- آرایه
   SELECT * FROM products WHERE 'tag1' = ANY(tags);

   -- همپوشانی آرایه
   SELECT * FROM products WHERE tags && ARRAY['tag1', 'tag2'];
  1. 1Date Functions:
sql
-- فاصله زمانی
   WHERE created_at >= NOW() - INTERVAL '30 days'

   -- گروه‌بندی بر اساس ماه
   DATE_TRUNC('month', created_at)

   -- استخراج
   EXTRACT(YEAR FROM created_at)
  1. 1COALESCE و NULLIF:
sql
-- مقدار پیش‌فرض
   COALESCE(phone, 'ندارد')

   -- جلوگیری از تقسیم بر صفر
   amount / NULLIF(quantity, 0)
  1. 1LATERAL JOIN: جستجوی پیشرفته:
sql
SELECT c.name, latest_order.*
   FROM customers c
   CROSS JOIN LATERAL (
     SELECT * FROM orders
     WHERE customer_id = c.id
     ORDER BY created_at DESC
     LIMIT 1
   ) latest_order
  1. 1Materialized View: کش کوئری‌های سنگین:
sql
CREATE MATERIALIZED VIEW monthly_report AS
   SELECT ... FROM ... GROUP BY ...;

   -- بروزرسانی
   REFRESH MATERIALIZED VIEW monthly_report;
  1. 1Index Types:
sql
-- B-tree (پیش‌فرض)
   CREATE INDEX idx_email ON users(email);

   -- GIN (برای JSONB و آرایه)
   CREATE INDEX idx_data ON orders USING GIN (data);

   -- GiST (برای Full-text Search)
   CREATE INDEX idx_search ON articles USING GiST (search_vector);

   -- Partial Index
   CREATE INDEX idx_active ON users(email) WHERE active = true;
  1. 1Explain Analyze: تحلیل Performance:
sql
EXPLAIN ANALYZE SELECT * FROM orders WHERE status = 'new';
  1. 1Generate Series: تولید داده:
sql
-- تولید تاریخ‌های 30 روز اخیر
    SELECT generate_series(
      CURRENT_DATE - INTERVAL '30 days',
      CURRENT_DATE,
      '1 day'
    )::date as date
  1. 1String Functions:
sql
-- ترکیب با جداکننده
    string_agg(name, ', ')

    -- فرمت عدد
    to_char(amount, '999,999,999')

    -- Regex
    SELECT * FROM users WHERE email ~ '^[a-z]+@gmail\.com$'
  1. 1تبدیل قیمت ریال به تومان:
sql
SELECT name,
      to_char(price / 10, 'FM999,999,999') || ' تومان' as price_display
    FROM products
  1. 1Recursive CTE: درخت‌واره:
sql
WITH RECURSIVE category_tree AS (
      SELECT id, name, parent_id, 0 as depth
      FROM categories WHERE parent_id IS NULL
      UNION ALL
      SELECT c.id, c.name, c.parent_id, ct.depth + 1
      FROM categories c
      JOIN category_tree ct ON c.parent_id = ct.id
    )
    SELECT * FROM category_tree ORDER BY depth, name
  1. 1Connection Pooling: از PgBouncer استفاده کنید برای مدیریت بهتر اتصال‌ها.
  1. 1دسترسی به نتایج در n8n:
javascript
// فیلد خاص
    {{$json.id}}

    // تعداد رکوردها
    {{$json.length}}

    // RETURNING fields
    {{$json.id}} // ID رکورد جدید

رفع مشکلات

خطاهای رایج

1. خطای "Connection refused"

علت: PostgreSQL روشن نیست یا پورت بسته است

راه‌حل

  • وضعیت سرویس: sudo systemctl status postgresql
  • پورت را چک کنید: sudo ss -tlnp | grep 5432
  • postgresql.conf: listen_addresses = '*'
  • Firewall: sudo ufw allow 5432

2. خطای "Authentication failed"

علت: کاربر یا رمز اشتباه

راه‌حل

  • pg_hba.conf را بررسی کنید
  • رمز عبور ریست:
sql
ALTER USER n8n_user WITH PASSWORD 'new_password';
  • نوع Authentication: scram-sha-256 یا md5

3. خطای "Permission denied for table"

علت: کاربر دسترسی لازم ندارد

راه‌حل

sql
GRANT SELECT, INSERT, UPDATE, DELETE
ON ALL TABLES IN SCHEMA public
TO n8n_user;

4. خطای SSL connection

علت: تنظیمات SSL نادرست

راه‌حل

  • SSL Mode را require بگذارید
  • اگر self-signed: sslmode=require (بدون verify)
  • برای Production: CA certificate را اضافه کنید

5. خطای "Relation does not exist"

علت: جدول پیدا نشد

راه‌حل

  • Schema را مشخص کنید: public.my_table
  • جداول را ببینید:
sql
SELECT table_name FROM information_schema.tables
  WHERE table_schema = 'public';

6. خطای "Value too long for type"

علت: داده بزرگتر از نوع ستون

راه‌حل

sql
ALTER TABLE my_table ALTER COLUMN description TYPE TEXT;

7. خطای "Deadlock detected"

علت: دو تراکنش همزمان منتظر هم‌اند

راه‌حل

  • ترتیب عملیات را یکسان کنید
  • از SELECT ... FOR UPDATE SKIP LOCKED استفاده کنید
  • تراکنش‌ها را کوتاه نگه دارید
اشتراک‌گذاری:

آیا این مستندات مفید بود؟