รับการจับคู่บางส่วนจากคอลัมน์ TSVECTOR ที่จัดทำดัชนีโดย GIN


13

ฉันต้องการได้รับผลลัพธ์จากแบบสอบถามนี้:

SELECT * FROM (
  SELECT id, subject
  FROM mailboxes
  WHERE tsv @@ plainto_tsquery('avail')
) AS t1 ORDER by id DESC;

งานนี้และแถวกลับมาพร้อมกับมีtsv Availableแต่ถ้าฉันใช้avai(ดร็อปlable) มันไม่สามารถหาอะไรได้เลย

คำค้นหาทั้งหมดต้องอยู่ในพจนานุกรมหรือไม่ เราไม่สามารถค้นหาจดหมายเช่นนั้นได้หรือ ฉันมีฐานข้อมูลที่มีเนื้อหาอีเมล (เนื้อหา) และฉันต้องการทำให้มันเร็วขึ้นเรื่อย ๆ ทุกวัน ขณะนี้ฉันกำลังใช้

... WHERE content ~* 'letters`

คำตอบ:


22

คำค้นหาทั้งหมดต้องอยู่ในพจนานุกรมหรือไม่

ไม่เพราะมีเพียงคำที่เกิดขึ้น (ตามการกำหนดค่าการค้นหาข้อความที่ใช้) อยู่ในดัชนีเพื่อเริ่มต้น แต่ที่สำคัญกว่า:

ไม่ เพราะที่ด้านบนของการค้นหาข้อความแบบเต็มนั้นก็สามารถจับคู่คำนำหน้าได้ :

สิ่งนี้จะได้ผล:

SELECT id, subject
FROM   mailboxes
WHERE  tsv @@ to_tsquery('simple', 'avail:*')
ORDER  BY id DESC;

หมายเหตุ3สิ่ง:

  1. ใช้to_tsquery()ไม่ใช่plainto_tsquery()ในกรณีนี้เพราะ ( อ้างถึงคู่มือ ):

    ... plainto_tsqueryจะไม่รู้จักtsqueryตัวดำเนินการป้ายกำกับน้ำหนักหรือฉลากจับคู่คำนำหน้าในข้อมูลที่ป้อน

  2. ใช้การ'simple'กำหนดค่าการค้นหาข้อความเพื่อสร้างtsqueryสิ่งที่ชัดเจนเนื่องจากคุณต้องการใช้คำว่า'ประโยชน์'อย่างที่เป็นอยู่และไม่ได้ใช้การกั้น

  3. ผนวก:*เพื่อทำให้เป็นการค้นหาคำนำหน้าเช่นค้นหาคำศัพท์ทั้งหมดที่เริ่มต้นด้วย 'ประโยชน์'

สำคัญ: นี่คือการค้นหาคำนำหน้าคำศัพท์ (stems คำ) ในเอกสาร การจับคู่นิพจน์ทั่วไปที่ไม่มี wildcard ( content ~* 'avail') ไม่เหมือนกันทุกประการ! หลังไม่ได้ยึดติดกับด้านซ้าย (จนถึงจุดเริ่มต้นของคำศัพท์) และจะพบ 'FOOavail' เป็นต้น

มันไม่ชัดเจนว่าคุณต้องการให้พฤติกรรมที่ระบุไว้ในแบบสอบถามของคุณหรือเทียบเท่าของการแสดงออกปกติเพิ่ม ดัชนี Trigram ( pg_trgm) เช่น@Evan ที่แนะนำไปแล้วเป็นเครื่องมือที่เหมาะสมสำหรับสิ่งนั้น มีคำถามที่เกี่ยวข้องจำนวนมากใน dba.SE จะพยายามค้นหา

ข้อมูลทั่วไป:

การสาธิต

SELECT *
FROM (
   VALUES
     ('Zend has no framework')
   , ('Zend Framework')
   ) sub(t), to_tsvector(t) AS tsv
WHERE tsv @@ to_tsquery('zend <-> fram:*');
 id |       t        |          tsv
----+----------------+------------------------
  2 | Zend Framework | 'framework':2 'zend':1

คำตอบที่เกี่ยวข้องล่าสุด (บทที่วิธีที่แตกต่างเพื่อเพิ่มประสิทธิภาพการค้นหา ):

อีเมล์?

เนื่องจากคุณพูดถึงอีเมลโปรดทราบว่าตัวแยกวิเคราะห์การค้นหาข้อความจะระบุอีเมลและจะไม่แยกออกเป็นคำ / lexemes แยกกัน พิจารณา:

SELECT ts_debug('english', 'xangr@some.domain.com')
(email,"Email address",xangr@some.domain.com,{simple},simple,{xangr@some.domain.com})

ฉันจะแทนที่ตัวคั่น@และ.ในอีเมลของคุณด้วย space ( ' ') เพื่อจัดทำดัชนีคำที่มี

นอกจากนี้ตั้งแต่คุณจะจัดการกับชื่อในอีเมลไม่ได้กับภาษาอังกฤษ (หรือบางภาษาอื่น) คำพูดผมจะใช้'simple'การตั้งค่าการค้นหาข้อความที่จะปิดกั้นและอื่น ๆภาษาคุณสมบัติ:

สร้างts_vectorคอลัมน์ด้วย:

SELECT to_tsvector('simple', translate('joe.xangr@some.domain.com', '@.', '  ')) AS tsv;

ฉันกำลังลบคำตอบสำหรับเรื่องนี้เพราะอย่างใดเพราะฉันผิดอย่างชัดเจนเป็นครั้งแรกและฉันก็ไม่ได้ถูกเตือน ฉันมีคำถามสองข้อสำหรับคุณ 1) ที่มีการ:*บันทึกไว้และ 2) ไม่ควรพูดถึงการสร้างto_tsvector('simple'..)มาพร้อมกับคำแนะนำที่การสอบถามในอนาคตของ TSV นั้นจะต้องมีการกำหนดค่า 'ง่าย' เกินไป tsquery? ฉันคิดว่าคุณควรอธิบายถึงการแตกกิ่งก้านของการปิดการใช้งานการกำเนิดใน tsvector / tsquery
Evan Carroll

@EvanCarroll: การใช้ 'ง่าย' การตั้งค่าจะไม่จำเป็นต้องใช้ มันเพียงหลีกเลี่ยงการกั้น (เช่น 'หนู' เป็น 'หนู') ซึ่งอาจหรืออาจไม่เป็นที่ต้องการ ไม่พึงประสงค์สำหรับตัวอย่างที่กำหนด คู่มือ: ฉันได้เพิ่มลิงค์ด้านบน ...
Erwin Brandstetter

4
@EvanCarroll: นอกเหนือจาก: การคิดว่าคุณผิดครั้งแรกจะเป็นครั้งที่สอง และนั่นจะเป็นสิ่งที่ผิดซ้ำซาก ;)
Erwin Brandstetter

2
@ErwinBrandstetter ว้าววิธีการของคุณเพียงแค่ให้ฉันค้นหาด้วยความเร็วเต็ม ก่อนที่วิธีของคุณ0.380msจะได้ผลลัพธ์ 0.079 msหลังจากที่ทางของคุณมันต้องใช้เวลา
xangr

1
@xangr: ไม่ FTS นำเสนอการจับคู่คำนำหน้าสำหรับคำศัพท์เท่านั้น pg_trgmอะไรเพิ่มเติมดูที่ FTS เร็วขึ้น (พร้อมดัชนีที่เล็กกว่า) คุณสามารถรวมดัชนีทั้งสองเข้าด้วยกัน ...
Erwin Brandstetter
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.