🐘
پستگرس
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در n8n به بخش Credentials بروید
- 2PostgreSQL را انتخاب کنید
- 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)
- 1SSL Mode:
requireیاverify-full - 2CA Certificate: محتوای
ca-cert.pem - 3Client Certificate: (اختیاری)
- 4Client Key: (اختیاری)
روش 4: SSH Tunnel
برای سرورهایی که دسترسی مستقیم ندارند:
- 1SSH Host و Port
- 2SSH User و Password/Key
- 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_at2. جستجوی 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 204. سیستم لاگگیری
ذخیره لاگهای فعالیت:
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 DESC5. 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 DESC7. 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 employees8. سیستم اعلان با 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 HEADER10. گزارش داشبورد
آمار کلی برای داشبورد:
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 (ارسال)نکات حرفهای
نکات حرفهای
- 1RETURNING: بعد از INSERT/UPDATE نتیجه بگیرید:
sql
INSERT INTO users (name, email)
VALUES ('Ali', 'ali@test.com')
RETURNING id, created_at;- 1JSONB Operators: عملگرهای JSON:
sql
-- دسترسی به فیلد (text)
data->>'name'
-- دسترسی تودرتو (json)
data->'address'->'city'
-- بررسی وجود کلید
data ? 'email'
-- بروزرسانی JSON
data || '{"status": "active"}'::jsonb
-- حذف کلید
data - 'temp_field'- 1Array Operations:
sql
-- آرایه
SELECT * FROM products WHERE 'tag1' = ANY(tags);
-- همپوشانی آرایه
SELECT * FROM products WHERE tags && ARRAY['tag1', 'tag2'];- 1Date Functions:
sql
-- فاصله زمانی
WHERE created_at >= NOW() - INTERVAL '30 days'
-- گروهبندی بر اساس ماه
DATE_TRUNC('month', created_at)
-- استخراج
EXTRACT(YEAR FROM created_at)- 1COALESCE و NULLIF:
sql
-- مقدار پیشفرض
COALESCE(phone, 'ندارد')
-- جلوگیری از تقسیم بر صفر
amount / NULLIF(quantity, 0)- 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- 1Materialized View: کش کوئریهای سنگین:
sql
CREATE MATERIALIZED VIEW monthly_report AS
SELECT ... FROM ... GROUP BY ...;
-- بروزرسانی
REFRESH MATERIALIZED VIEW monthly_report;- 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;- 1Explain Analyze: تحلیل Performance:
sql
EXPLAIN ANALYZE SELECT * FROM orders WHERE status = 'new';- 1Generate Series: تولید داده:
sql
-- تولید تاریخهای 30 روز اخیر
SELECT generate_series(
CURRENT_DATE - INTERVAL '30 days',
CURRENT_DATE,
'1 day'
)::date as date- 1String Functions:
sql
-- ترکیب با جداکننده
string_agg(name, ', ')
-- فرمت عدد
to_char(amount, '999,999,999')
-- Regex
SELECT * FROM users WHERE email ~ '^[a-z]+@gmail\.com$'- 1تبدیل قیمت ریال به تومان:
sql
SELECT name,
to_char(price / 10, 'FM999,999,999') || ' تومان' as price_display
FROM products- 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- 1Connection Pooling: از PgBouncer استفاده کنید برای مدیریت بهتر اتصالها.
- 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استفاده کنید - تراکنشها را کوتاه نگه دارید
اشتراکگذاری:
