ฉันจะค้นหาโดยใช้ฟิลด์ภายในประเภทข้อมูล PostgreSQL JSON ใหม่ได้อย่างไร


216

ฉันกำลังมองหาเอกสารและ / หรือตัวอย่างสำหรับฟังก์ชั่น JSON ใหม่ใน PostgreSQL 9.2

โดยเฉพาะรับชุดของบันทึก JSON:

[
  {name: "Toby", occupation: "Software Engineer"},
  {name: "Zaphod", occupation: "Galactic President"}
]

ฉันจะเขียน SQL เพื่อค้นหาระเบียนด้วยชื่อได้อย่างไร

ในวานิลลา SQL:

SELECT * from json_data WHERE "name" = "Toby"

คู่มือ dev อย่างเป็นทางการค่อนข้างกระจัดกระจาย:

อัปเดตฉัน

ฉันได้ใส่กันสรุปสาระสำคัญรายละเอียดสิ่งที่เป็นอยู่ในปัจจุบันเป็นไปได้กับ PostgreSQL 9.2 เมื่อใช้ฟังก์ชั่นที่กำหนดเองคุณสามารถทำสิ่งต่าง ๆ เช่น:

SELECT id, json_string(data,'name') FROM things
WHERE json_string(data,'name') LIKE 'G%';

อัปเดต II

ตอนนี้ฉันได้ย้ายฟังก์ชั่น JSON ของฉันไปที่โครงการของตัวเอง:

PostSQL - ชุดฟังก์ชั่นสำหรับเปลี่ยน PostgreSQL และ PL / v8 เป็นที่เก็บเอกสาร JSON ที่ยอดเยี่ยมโดยสิ้นเชิง


3
เพิ่งพบโพสต์บล็อกนี้โดย Matt Schinckel ซึ่งอธิบายในรายละเอียดการสืบค้น JSON ใน PostgreSQL schinckel.net/2014/05/25/querying-json-in-postgres
knowbody

1
@knowbody โพสต์นี้เป็นจริงเกี่ยวกับการสืบค้น JSONB ซึ่งค่อนข้างแตกต่างจาก JSON ฉันไม่ดีที่ไม่ทำให้ชัดเจนในโพสต์
Matthew Schinckel

คำตอบ:


177

Postgres 9.2

ฉันอ้างอิงAndrew Dunstan ในรายการ pgsql-hackers :

ในบางขั้นตอนอาจมีฟังก์ชั่นการประมวลผล json (ซึ่งต่างจากฟังก์ชั่นการผลิต json) แต่ไม่ใช่ใน 9.2

ไม่ได้ป้องกันเขาจากการให้ตัวอย่างการนำไปใช้ใน PLV8ที่ควรแก้ปัญหาของคุณ

Postgres 9.3

เสนอคลังแสงของฟังก์ชั่นใหม่และผู้ประกอบการเพื่อเพิ่ม "การประมวลผล json"

คำตอบของคำถามต้นฉบับใน Postgres 9.3:

SELECT *
FROM   json_array_elements(
  '[{"name": "Toby", "occupation": "Software Engineer"},
    {"name": "Zaphod", "occupation": "Galactic President"} ]'
  ) AS elem
WHERE elem->>'name' = 'Toby';

ตัวอย่างขั้นสูง:

สำหรับตารางที่ใหญ่กว่าคุณอาจต้องการเพิ่มดัชนีนิพจน์เพื่อเพิ่มประสิทธิภาพ:

Postgres 9.4

เพิ่มjsonb(b สำหรับ "ไบนารี่" ค่าจะถูกจัดเก็บเป็นชนิด Postgres ดั้งเดิม) และยังมีฟังก์ชันการทำงานเพิ่มเติมสำหรับทั้งสองประเภท นอกเหนือจากดัชนีนิพจน์ที่กล่าวถึงข้างต้นแล้วjsonbยังสนับสนุนGIN, btree และ hash index , GIN นั้นมีศักยภาพมากที่สุด

คู่มือไปถึงเท่าที่แนะนำ:

โดยทั่วไปแอปพลิเคชันส่วนใหญ่ควรเก็บข้อมูล JSON เป็น jsonbเว้นแต่มีความต้องการค่อนข้างพิเศษเช่นสมมติฐานดั้งเดิมเกี่ยวกับการสั่งซื้อคีย์วัตถุ

เหมืองเน้นหนัก

ประโยชน์ด้านประสิทธิภาพจากการปรับปรุงทั่วไปสำหรับดัชนี GIN

Postgres 9.5

jsonbฟังก์ชั่นที่สมบูรณ์และผู้ประกอบการ เพิ่มฟังก์ชั่นเพิ่มเติมเพื่อจัดการกับjsonbสถานที่และสำหรับการแสดงผล


1
ขอบคุณฉันพบปัญหาประเภทอย่างรวดเร็วโดยใช้วิธี PLV8 ดูมีแนวโน้ม แต่ไม่สามารถใช้งานได้ในขณะนี้
Toby Hede

@TobyHede: เดาว่าเราจะต้องรอ 9.3 แล้ว
Erwin Brandstetter

1
@JoeShaw: ขอบคุณฉันอัปเดตตามนั้นและเพิ่มลิงค์ไปยัง Postgres Wiki
Erwin Brandstetter

@ErwinBrandstetter หากฉันกำลังมองหาสถานที่อื่น ๆ - >> 'ถูกต้อง' = 'TRUE'; และ JSON มีลักษณะเช่นนี้: "ถูกต้อง": "TRUE" วิธีที่ถูกต้องในการสืบค้นคำศัพท์ตรรกะคืออะไร?
Shiraj

@Shiraj: กรุณาถามคำถามใหม่เป็นคำถาม ความเห็นไม่ใช่สถานที่
Erwin Brandstetter

87

ด้วย Postgres 9.3+ เพียงใช้->โอเปอเรเตอร์ ตัวอย่างเช่น,

SELECT data->'images'->'thumbnail'->'url' AS thumb FROM instagram;

ดูhttp://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/สำหรับตัวอย่างที่ดีและการสอน


2
ในตัวอย่างข้างต้นคุณควรจะมีข้อมูลที่มีชื่อdataกับเอกสาร {images:{thumbnail:{url:'thumbnail.jpg'}}}JSON: แจ้งให้เราทราบว่าข้อมูลของคุณเป็นอย่างไรและแบบสอบถามใดล้มเหลว
Meekohi


6
คุณจะค้นหาได้อย่างไรถ้ามีอาเรย์ ฉันเห็นโอเปอเรเตอร์ # >> แต่ไม่รู้ว่าจะใช้ยังไง!
Mohamed El Mahallawy

ในแบบสอบถามแบบใช้เลือกข้อมูลนี้ฉันสามารถใช้อักขระตัวแทนได้ไหม IeSELECT data->'%'->'thumbnail'->'url' AS thumb FROM instagram;
Bharat

@ คำตอบของ Meekohi ทำงานได้ดี: โดยเฉพาะฉันไม่ต้องการ::jsonตามที่อธิบายไว้ในโพสต์อื่น นอกจากนี้โปรดทราบว่า->ผู้ให้บริการจะโยนข้อผิดพลาดหากคุณพยายามเข้าถึงคุณสมบัติที่ไม่มีอยู่ (เช่นหากคุณมี JSON ที่เซ):ERROR: column "jsonPropertyYouWant" does not exist
The Red Pea

19

ด้วย postgres 9.3 ให้ใช้ -> สำหรับการเข้าถึงวัตถุ 4 ตัวอย่าง

seed.rb

se = SmartElement.new
se.data = 
{
    params:
    [
        {
            type: 1,
            code: 1,
            value: 2012,
            description: 'year of producction'
        },
        {
            type: 1,
            code: 2,
            value: 30,
            description: 'length'
        }
    ]
}

se.save

c. ราง

SELECT data->'params'->0 as data FROM smart_elements;

ผลตอบแทน

                                 data
----------------------------------------------------------------------
 {"type":1,"code":1,"value":2012,"description":"year of producction"}
(1 row)

คุณสามารถทำรังต่อได้

SELECT data->'params'->0->'type' as data FROM smart_elements;

กลับ

 data
------
 1
(1 row)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.