Postgresql

每個屬性具有多個值的 EAV

  • July 28, 2017

我正在開發具有廣泛類別(電視、手機、家具等)的電子商務網站。由於有這麼多的屬性,我決定使用 EAV 模型來儲存屬性和值。這是我的表結構:

CREATE TABLE public.product_attribute
(
   name character varying(255) COLLATE pg_catalog."default",
   attribute_type character varying(255) COLLATE pg_catalog."default",
   id integer NOT NULL,
   CONSTRAINT product_attribute_pkey PRIMARY KEY (id)
)

CREATE TABLE public.product_attribute_value
(
   value_text text COLLATE pg_catalog."default",
   value_integer integer,
   value_boolean boolean,
   value_float double precision,
   value_richtext text COLLATE pg_catalog."default",
   value_date date,
   value_file character varying(255) COLLATE pg_catalog."default",
   value_image character varying(255) COLLATE pg_catalog."default",
   entity_object_id integer,
   attribute_id integer,
   product_id integer,
   id integer NOT NULL,
   CONSTRAINT product_attribute_value_pkey PRIMARY KEY (id),
   CONSTRAINT "product_attr_id" FOREIGN KEY (attribute_id)
       REFERENCES public.product_attribute (id) MATCH SIMPLE
       ON UPDATE NO ACTION
       ON DELETE NO ACTION
)

假設我要添加一台新電視。

Product
---------
id: 1
name: Sony TV

Product Attribute
-----------------
id: 1
name: Color

Product Attribute Value
-----------------------
id: 1
attribute_id: 1
value_text: white

我面臨的問題是,對於某些產品(如家具),有多個具有相同名稱的屬性(例如顏色),不僅如此,我還需要儲存圖像照片 url。

Product
---------
id: 2
name: Table

Product Attribute Value
-----------------------
id: 3
attribute_id: 1
value_text: Pattern 1
value_image: 01/a0/01a0sdadasfsdfsdfasdfasfdfsafs.jpg
=======================
id: 4
attribute_id: 1
value_text: Pattern 2
value_image: 01/a2/01a234234234234234324324234234.jpg

獲取具有所有屬性的產品的最佳方法是什麼?我不太擔心按屬性值過濾的查詢性能(因為所有數據都同步到 elasticsearch 並從那裡獲取)。但是有幾百萬種產品。有沒有辦法通過一個查詢(一個產品-> 一行)獲取具有所有屬性的每個產品?

我認為 JSONB 不是儲存此屬性的最佳主意,因為它們經常更新,我不想搜尋和更新數百萬條記錄來重命名屬性名稱。

你的答案

多個具有相同名稱的屬性(例如顏色),

因此,然後創建一個具有更多特異性的不同屬性。

我還需要儲存圖像照片網址。

這只是另一個屬性…

Product Attribute
-----------------
2 | photo_exterior

Product Attribute Value
-----------------------
id: 1
attribute_id: 2
value: 01/a0/01a0sdadasfsdfsdfasdfasfdfsafs.jpg

綜上所述,除非必須,否則我不會這樣做。我將使用 JSONB。

獲取具有所有屬性的產品的最佳方法是什麼?

我不確定你想要什麼樣的結果集。您是在問如何查詢 EAV?如果你能做到,你當然可以進行連接以獲得結果集。

有沒有辦法通過一個查詢(一個產品-> 一行)獲取具有所有屬性的每個產品?

是的,如果你不知道你有多少屬性,你最終可能會使用hstoreorthough jsonb。看jsonb_agg()

XY 問題?

檢查速度以便讓您重新評估 JSONB 並挽救您的生命。創建一百萬個產品,使用 jsonb 重命名屬性。

CREATE TABLE products(id,name,data)
AS
       SELECT x, 'foo'::text, jsonb_build_object('color', 'blue') AS data
       FROM generate_series(1,1e6) AS gs(x);


UPDATE products
SET data = data-'color' || jsonb_build_object('colour', data->'color');
Time: 5063.010 ms

在我的 x230 筆記型電腦上,帶有 SSD。那是 197 行/毫秒?您重新創建了必須比這更快更新的亞馬遜?

引用自:https://dba.stackexchange.com/questions/182029