ftrack query เป็น wrapper ที่มุ่งเน้นวัตถุเหนือ FTRACK API ในขณะที่ไวยากรณ์การสืบค้นเริ่มต้นนั้นมีประสิทธิภาพ แต่เป็นข้อความทั้งหมดที่ใช้ข้อความแบบไดนามิกอาจสร้างได้ยาก โมดูลนี้รองรับ และ / หรือ ผู้ประกอบการที่มีการเปรียบเทียบแบบซ้อนกัน
ขอแนะนำให้อ่าน https://ftrack-python-api.readthedocs.io/en/stable/tutorial.html ก่อนเพื่อทำความเข้าใจขั้นพื้นฐานว่า FTRACK API ทำงานอย่างไร
pip install ftrack_query
แทนที่จะเขียนสตริงแบบสอบถามทั้งหมดในครั้งเดียว "คำสั่ง" ถูกสร้างขึ้น ( เช่น stmt = select('Task') ) และสามารถสร้างแบบสอบถามได้โดยวิธีการโทรเช่น .where() และ .populate() ในคำสั่ง
วิธีการ CRUD ทั้งหมดได้รับการสนับสนุน ( create , select , update , delete ) แต่ฟังก์ชั่นหลักได้รับการออกแบบมาเพื่อใช้กับ select ข้อความถูกสร้างขึ้นด้วยไวยากรณ์ที่คล้ายกันกับ API หลักดังนั้นควรตรงไปตรงมาเพื่อเปลี่ยนระหว่างทั้งสอง
โปรดทราบว่าสิ่งนี้เข้ากันได้อย่างสมบูรณ์แบบย้อนหลังดังนั้นแบบสอบถามที่มีอยู่จึงไม่จำเป็นต้องเขียนใหม่
ตัวอย่างด้านล่างนี้สำหรับการสืบค้นพื้นฐานมาก:
from ftrack_query import FTrackQuery , attr , create , select , and_ , or_
with FTrackQuery () as session :
# Select
project = session . select ( 'Project' ). where ( name = 'Test Project' ). one ()
# Create
task = session . execute (
create ( 'Task' ). values (
name = 'My Task' ,
project = project ,
)
)
session . commit ()
# Update
rows_updated = session . execute (
update ( 'Task' )
. where ( name = 'Old Task Name' )
. values ( name = 'New Task Name' )
)
session . commit ()
# Delete
rows_deleted = session . execute (
delete ( 'Task' ). where (
name = 'Old Task Name' ,
)
)
session . commit ()สำหรับตัวอย่างที่ซับซ้อนมากขึ้น:
ATTR_TYPE = attr ( 'type.name' )
TASK_STMT = (
select ( 'Task' )
# Filter the tasks
. where (
# Get any task without these statuses
~ attr ( 'status.name' ). in_ ([ 'Lighting' , 'Rendering' ]),
# Check for notes matching any of the following conditions:
attr ( 'notes' ). any (
# Ensure note was posted by someone outside the company
~ attr ( 'user.email' ). endswith ( '@company.com' )
# Ensure note either not completable or not completed
or_ (
and_ (
completed_by = None ,
is_todo = True ,
),
is_todo = False ,
),
),
# Ensure it has an animation task
or_ (
ATTR_TYPE . contains ( 'Animation' ),
ATTR_TYPE == 'Anim_Fixes' ,
),
),
# Order the results
. order_by (
ATTR_TYPE . desc (), # Equivalent to "type.name desc"
'name' ,
)
# Use projections to populate attributes as part of the query
. populate (
'name' ,
'notes' ,
'status.name' ,
ATTR_TYPE ,
)
. limit ( 5 )
)
with FTrackQuery () as session :
# Filter the above query to the result of another query
task_stmt = TASK_STMT . where (
project_id = session . select ( 'Project' ). where ( name = 'Test Project' ). one ()[ 'id' ]
)
# Use the current session to execute the statement
tasks = session . execute ( task_stmt ). all ()ระบบเหตุการณ์ใช้ภาษาคิวรีที่แตกต่างกันเล็กน้อย
from ftrack_query import FTrackQuery , event
from ftrack_query . event import attr , and_ , or_
with FTrackQuery () as session :
session . event_hub . subscribe ( str (
and_ (
attr ( 'topic' ) == 'ftrack.update' ,
attr ( 'data.user.name' ) != getuser (),
)
))
session . event_hub . wait () โปรดทราบว่า attr() and_() และ or_() มีอยู่ในทั้ง ftrack_query และ ftrack_query.event สิ่งเหล่านี้ ไม่ สามารถเปลี่ยนได้ดังนั้นหากต้องการทั้งสองอย่างให้นำเข้า event และใช้เป็นเนมสเปซ
เซสชันหลักที่สืบทอดมาจาก ftrack_api.Session
เข้าร่วมการเปรียบเทียบหลายครั้ง
ทางลัดมีให้กับ & และ | ( เช่น attr(a).contains(b) & attr(x).contains(y) )
ย้อนกลับการเปรียบเทียบอินพุต
ทางลัดมี ~ ( เช่น ~attr(x).contains(y) )
ใช้สำหรับการสร้างสตริงแบบสอบถาม
from ftrack_query import select
stmt = select ( entity ). where (...). populate (...) การโทร session.execute(stmt) จะดำเนินการค้นหาและส่งคืนวัตถุ QueryResult ของ Ftrack ซึ่งเป็นสิ่ง .one() ,. .first() หรือ .all() อาจถูกเรียก อีกทางเลือกหนึ่งโดยใช้ทางลัด session.select(entity) จากนั้นอาจถูกข้ามไป
กรองผลลัพธ์
การใช้คำหลักเป็นวิธีที่เร็วที่สุดเช่น .where(first_name='Peter', last_name='Hunt') สำหรับสิ่งที่ซับซ้อนกว่าการตรวจสอบความเท่าเทียมกันแนะนำให้ใช้ attr() เช่น .where(attr('project.metadata').any(attr('key') != 'disabled'))
แอตทริบิวต์เอนทิตีล่วงหน้า
ตัวอย่างเพื่อทำซ้ำชื่อของผู้ใช้ทุกคนมันเป็นความคิดที่ดีที่จะโทร .populate('first_name', 'last_name') เป็นส่วนหนึ่งของการสืบค้น หากไม่มีสิ่งนั้นจะต้องใช้แบบสอบถาม 2 แบบแยกต่อผู้ใช้ซึ่งเรียกว่าปัญหาการสืบค้น N+1
เรียงลำดับผลลัพธ์ด้วยแอตทริบิวต์
แอตทริบิวต์และคำสั่งซื้อสามารถให้ในรูปแบบ attr('name').desc() หรือเป็นสตริงดิบเช่น name descending คำสั่งซื้อจะเริ่มต้นที่ ascending หากไม่ได้ให้
ย้อนกลับทิศทางการเรียงลำดับ
จำกัด จำนวนผลลัพธ์เป็นค่าที่แน่นอน
หมายเหตุ: นี่ไม่เข้ากันกับการโทร .first() หรือ .one()
ในกรณีของการใช้ขีด จำกัด ให้ใช้การชดเชยกับผลลัพธ์ที่ส่งคืน
สำหรับผู้ใช้ขั้นสูงเท่านั้น
page_size : ตั้งค่าจำนวนผลลัพธ์ที่จะนำมาจาก FTRACK ครั้งเดียวsession : แนบวัตถุเซสชันกับแบบสอบถาม ทำให้คำสั่งเป็นคำถามย่อยสำหรับใช้ภายใน .in_()
สิ่งนี้ทำให้มั่นใจได้ว่าจะมี "เลือกจาก" เป็นส่วนหนึ่งของคำสั่งเสมอ การตั้งค่าพารามิเตอร์แอตทริบิวต์ด้วยตนเองจะแทนที่การคาดการณ์ที่มีอยู่
ใช้สำหรับการสร้างเอนทิตีใหม่
from ftrack_query import create
stmt = create ( entity ). values (...) การโทร session.execute(stmt) จะส่งคืนเอนทิตีที่สร้างขึ้น
ค่าเพื่อสร้างเอนทิตีด้วย
ใช้สำหรับแบทช์การอัปเดตค่าในหลายเอนทิตี สิ่งนี้ถูกสร้างขึ้นจากวิธี select ดังนั้นจึงมีวิธีการเดียวกันมากมาย
from ftrack_query import update
stmt = update ( entity ). where (...). values (...) การโทร session.execute(stmt) จะส่งคืนจำนวนหน่วยงานที่พบและอัปเดต
กรองสิ่งที่ต้องอัปเดต
ค่าที่จะอัปเดตในเอนทิตี
ใช้เพื่อลบเอนทิตี สิ่งนี้ถูกสร้างขึ้นจากวิธี select ดังนั้นจึงมีวิธีการเดียวกันมากมาย
from ftrack_query import delete
stmt = delete ( entity ). where (...). options ( remove_components = True ) การโทร session.execute(stmt) จะส่งคืนจำนวนหน่วยงานที่ถูกลบ
กรองสิ่งที่ต้องอัปเดต
remove_components : ลบเอนทิตี Component ใด ๆ ออกจากทุก Location ที่มีก่อนที่จะถูกลบ สิ่งนี้ไม่ได้เปิดใช้งานโดยค่าเริ่มต้นเนื่องจากไม่สามารถย้อนกลับได้ วัตถุ Comparison ถูกออกแบบมาเพื่อแปลงข้อมูลเป็นสตริง มันมีตัวดำเนินการที่หลากหลายซึ่งสามารถใช้กับประเภทข้อมูลใด ๆ รวมถึงวัตถุ Comparison อื่น ๆ ฟังก์ชั่น attr เป็นทางลัดสำหรับสิ่งนี้
การเปรียบเทียบใด ๆ สามารถย้อนกลับด้วยคำนำหน้า ~ หรือฟังก์ชั่น not_
attr(key) == 'value'attr(key) > 5attr(key).like('value%')attr(key).after(arrow.now().floor('day'))attr(key).has(subkey='value')attr(key).any(subkey='value')attr(key).in_(subquery)การเปรียบเทียบอย่างง่าย
ทำการตรวจสอบเพื่อตรวจสอบว่าแอตทริบิวต์ตรงกับผลลัพธ์ใด ๆ หรือไม่
สิ่งนี้สามารถยอมรับคำถามย่อยเช่น .in_('select id from table where x is y') หรือรายการของรายการเช่น .in_(['x', 'y'])
ตรวจสอบว่าสตริงอยู่ในแบบสอบถามหรือไม่ ใช้เครื่องหมายเปอร์เซ็นต์เป็นตัวแทนถ้าใช้หรือไม่ like not_like ; ส่วนที่เหลือเป็นทางลัดและทำสิ่งนี้โดยอัตโนมัติ
ทดสอบความสัมพันธ์กับสเกลาร์และคอลเลกชัน
ทดสอบวันที่ แนะนำให้ใช้วัตถุ arrow
# Project
select ( 'Project' )
# Project where status is active
select ( 'Project' ). where ( status = 'active' )
# Project where status is active and name like "%thrones"
select ( 'Project' ). where ( attr ( 'name' ). like ( '%thrones' ), status = 'active' )
# session.query('Project where status is active and (name like "%thrones" or full_name like "%thrones")')
select ( 'Project' ). where ( or_ ( attr ( 'name' ). like ( '%thrones' ), attr ( 'full_name' ). like ( '%thrones' )), status = 'active' )
# session.query('Task where project.id is "{0}"'.format(project['id']))
select ( 'Task' ). where ( project = project )
# session.query('Task where project.id is "{0}" and status.type.name is "Done"'.format(project['id']))
select ( 'Task' ). where ( attr ( 'status.type.name' ) == 'Done' , project = project )
# session.query('Task where timelogs.start >= "{0}"'.format(arrow.now().floor('day')))
select ( 'Task' ). where ( attr ( 'timelogs.start' ) >= arrow . now (). floor ( 'day' ))
# session.query('Note where author has (first_name is "Jane" and last_name is "Doe")')
select ( 'Note' ). where ( attr ( 'author' ). has ( first_name = 'Jane' , last_name = 'Doe' ))
# session.query('User where not timelogs any ()')
select ( 'User' ). where ( ~ attr ( 'timelogs' ). any ())
# projects = session.query('select full_name, status.name from Project')
select ( 'Project' ). populate ( 'full_name' , 'status.name' )
# select name from Project where allocations.resource[Group].memberships any (user.username is "john_doe")
select ( 'Project' ). select ( 'name' ). where ( attr ( 'allocations.resource[Group].memberships' ). any ( attr ( 'user.username' ) == 'john_doe' ))
# Note where parent_id is "{version_id}" or parent_id in (select id from ReviewSessionObject where version_id is "{version_id}")
select ( 'Note' ). where ( or_ ( attr ( 'parent_id' ). in_ ( select ( 'ReviewSessionObject' ). where ( version_id = version_id ). subquery ()), parent_id = version_id ))