SQLAlchemy เทียบเท่ากับคำสั่ง SQL“ LIKE”


87

คอลัมน์แท็กมีค่าเช่น "apple banana orange" และ "strawberry banana lemon" ฉันต้องการค้นหาคำสั่งเทียบเท่า SQLAlchemy กับ

SELECT * FROM table WHERE tags LIKE "%banana%";

ฉันควรผ่านClass.query.filter()อะไรเพื่อทำสิ่งนี้?

คำตอบ:


177

คอลัมน์แต่ละคนมีวิธีการที่สามารถนำมาใช้ในการlike() query.filter()ระบุสตริงการค้นหาเพิ่ม%อักขระที่ด้านใดด้านหนึ่งเพื่อค้นหาเป็นสตริงย่อยในทั้งสองทิศทาง

tag = request.form["tag"]
search = "%{}%".format(tag)
posts = Post.query.filter(Post.tags.like(search)).all()

1
สมบูรณ์แบบ! คุณรู้หรือไม่ว่ามีวิธีที่ดีกว่าในการแยกความแตกต่างระหว่างแอปเปิ้ลและสับปะรดมากกว่าการเพิ่มช่องว่าง
Gary Oldfaber

3
วิธีที่ดีที่สุดคือทำให้ฐานข้อมูลของคุณเป็นปกติและเพิ่มตารางแยก 2 ตารางสำหรับแท็กและความสัมพันธ์ระหว่างแท็กกับงานจากนั้นใช้ JOIN แทน LIKE มิฉะนั้นใช่ดูเหมือนว่าคุณจะต้องมีตัวคั่นรอบ ๆ แต่ละแท็กในสตริง พื้นที่ชั้นนำไม่เพียงพอเนื่องจากยังมีปากกาและดินสอด้วย% ปากกา% หากคุณทำบางสิ่งเช่น "| แอปเปิ้ล | สับปะรด | ปากกา | ดินสอ |" และจับคู่ "% | ปากกา |%" ไม่ควรชนกัน
Daniel Kluev

1
ด้วยการทำให้เป็นมาตรฐานฉันไม่ค่อยแน่ใจว่าฉันจะมีแท็กมากกว่าหนึ่งแท็กที่เกี่ยวข้องกับงานที่กำหนดได้อย่างไรหรือในทางกลับกันโดยใช้แผนที่แท็ก โซลูชัน "Toxi" ดูเหมือนจะจัดกลุ่มการรวบรวมแท็กเป็นรายการเดียวแทนที่จะจัดเก็บทีละรายการ? และวิธีการที่ใช้ในสูตรนี้ ( elixir.ematia.de/trac/wiki/Recipes/TagCloud ) จะอนุญาตเพียงหนึ่งแท็กต่อรายการ แหล่งข้อมูลใดที่ดีที่สุดในการอธิบายหัวข้อนี้ ฉันได้อ่านสิ่งนี้ ( dev.mysql.com/tech-resources/articles/… ) ด้วย แต่ไม่สามารถนึกภาพวิธีจัดการหลายแท็กได้
Gary Oldfaber

2
อย่างที่ฉันบอกคุณต้องมีสองโต๊ะ โดยพื้นฐานแล้วมันเป็นเพียงความสัมพันธ์แบบกลุ่มต่อกลุ่มทั่วไปดังนั้นคุณสามารถทำตามคำแนะนำของ SQLAlchemy ได้ที่: sqlalchemy.org/docs/… คุณจะมีtagsตารางที่คุณเก็บชื่อแท็กและข้อมูลแท็กอื่น ๆ และคุณจะมีtask_tagsตารางซึ่ง จะมีหนึ่งระเบียนสำหรับแต่ละแท็กที่เพิ่มลงในงาน ดังนั้นงานที่มี 2 แท็กจะมี 2 ระเบียนในtask_tagsตาราง
Daniel Kluev

12

การเพิ่มคำตอบข้างต้นใครก็ตามที่กำลังมองหาวิธีแก้ปัญหาคุณสามารถลองใช้ตัวดำเนินการ "จับคู่" แทน "ชอบ" ได้ ไม่ต้องการที่จะลำเอียง แต่มันทำงานได้ดีสำหรับฉันใน Postgresql

Note.query.filter(Note.message.match("%somestr%")).all()

สืบทอดฟังก์ชันฐานข้อมูลเช่นCONTAINSและMATCH MATCHอย่างไรก็ตามไม่มีใน SQLite

สำหรับข้อมูลเพิ่มเติมไปที่Common Filter Operators


8
อะไรคือความแตกต่างระหว่างตัวดำเนินการทั้งสองนี้?
buhtz บอกว่ารับการฉีดวัคซีน

@buhtz ขึ้นอยู่กับแบ็กเอนด์ DB ของคุณดูเอกสาร SQL-Alchemy: docs.sqlalchemy.org/en/14/core/…ใน Postgres คุณจะได้รับto_tsqueryซึ่งช่วยให้คุณสามารถเพิ่มตัวดำเนินการข้อความสำหรับสิ่งต่างๆเช่นORและAND postgresql.org/docs/current/…
นิค


1

การใช้ PostgreSQL like( ดูคำตอบที่ยอมรับด้านบน ) อย่างใดก็ไม่ได้ผลสำหรับฉันแม้ว่าจะมีกรณีที่ตรงกันแต่ilike(กรณีที่ฉันไม่อ่อนไหวเช่น ) ทำ


2
ILIKEเป็นเวอร์ชันที่ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่LIKEดังนั้นอินพุตของคุณจึงแตกต่างกันในกรณีเท่านั้น
Martijn Pieters

0

หากคุณใช้ SQL แบบเนทีฟคุณสามารถอ้างถึงโค้ดของฉันมิฉะนั้นก็ไม่สนใจคำตอบของฉัน

SELECT * FROM table WHERE tags LIKE "%banana%";
from sqlalchemy import text

bar_tags = "banana"

# '%' attention to spaces
query_sql = """SELECT * FROM table WHERE tags LIKE '%' :bar_tags '%'"""

# db is sqlalchemy session object
tags_res_list = db.execute(text(query_sql), {"bar_tags": bar_tags}).fetchall()

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