การค้นหาเหมาะสมกับอินเทอร์เฟซ RESTful อย่างไร


137

เมื่อออกแบบอินเตอร์เฟส RESTful ซีแมนทิกส์ของประเภทคำขอจะถือว่ามีความสำคัญต่อการออกแบบ

  • GET - รายการคอลเลกชันหรือดึงองค์ประกอบ
  • PUT - แทนที่คอลเลกชันหรือองค์ประกอบ
  • POST - สร้างคอลเล็กชันหรือองค์ประกอบ
  • DELETE - เอออืมลบคอลเลกชันหรือองค์ประกอบ

อย่างไรก็ตามสิ่งนี้ดูเหมือนจะไม่ครอบคลุมแนวคิดของ "การค้นหา"

เช่นในการออกแบบชุดบริการเว็บที่สนับสนุนไซต์หางานคุณอาจมีข้อกำหนดต่อไปนี้:

  • รับโฆษณางานบุคคล
    • รับไปdomain/Job/{id}/
  • สร้างงานโฆษณา
    • โพสต์ถึงdomain/Job/
  • อัปเดตงานโฆษณา
    • ใส่ลงไปdomain/Job/
  • ลบโฆษณางาน
    • ลบไปที่domain/Job/

"รับงานทั้งหมด" ก็ง่าย:

  • รับไปdomain/Jobs/

อย่างไรก็ตามงาน "การค้นหา" ตกอยู่ในโครงสร้างนี้อย่างไร

คุณสามารถอ้างว่าเป็น "รูปแบบรายการ" และใช้เป็น:

  • รับไปdomain/Jobs/

อย่างไรก็ตามการค้นหาอาจซับซ้อนและเป็นไปได้ทั้งหมดในการสร้างการค้นหาที่สร้างสตริง GET ที่ยาว นั่นคือการอ้างอิงคำถาม SO ที่นี่มีปัญหาในการใช้สตริง GET ที่มีความยาวมากกว่า 2000 ตัวอักษร

ตัวอย่างอาจอยู่ในการค้นหาแบบเหลี่ยมเพชรพลอย - ดำเนินการต่อตัวอย่าง "job"

ฉันอาจอนุญาตให้ค้นหาในแง่มุม - "เทคโนโลยี", "ตำแหน่งงาน", "มีระเบียบวินัย" เช่นเดียวกับคำหลักที่เป็นข้อความอิสระอายุงานตำแหน่งและเงินเดือน

ด้วยอินเทอร์เฟซผู้ใช้ที่คล่องแคล่วและเทคโนโลยีและตำแหน่งงานจำนวนมากจึงเป็นไปได้ที่การค้นหาอาจรวมตัวเลือกด้านข้อมูลจำนวนมาก

ปรับแต่งตัวอย่างนี้เป็น CV แทนที่จะนำงานเข้ามาเพิ่มมากขึ้นและคุณสามารถจินตนาการได้อย่างง่ายดายว่าการค้นหาด้วยการเลือกร้อยหน้าหรือเพียง 40 แง่มุมแต่ละอันมีความยาว 50 ตัวอักษร (เช่นชื่องาน, ชื่อมหาวิทยาลัย, ชื่อนายจ้าง)

ในสถานการณ์ดังกล่าวอาจเป็นการดีที่จะย้าย PUT หรือ POST เพื่อให้แน่ใจว่าข้อมูลการค้นหาจะได้รับการส่งอย่างถูกต้อง เช่น:

  • โพสต์ถึงdomain/Jobs/

แต่ความหมายคือคำแนะนำในการสร้างคอลเลกชัน

นอกจากนี้คุณยังสามารถบอกได้ว่าคุณจะแสดงสิ่งนี้เป็นการสร้างการค้นหา:

  • โพสต์ถึงdomain/Jobs/Search/

หรือ (ตามที่แนะนำโดย burngramma ด้านล่าง)

  • โพสต์ถึงdomain/JobSearch/

ความหมายดูเหมือนจะสมเหตุสมผล แต่จริงๆแล้วคุณไม่ได้สร้างอะไรเลยคุณกำลังขอข้อมูล

ดังนั้นความหมายมันเป็นGETแต่GETไม่รับประกันว่าจะสนับสนุนสิ่งที่คุณต้องการ

ดังนั้นคำถามคือ - พยายามทำให้เป็นจริงกับการออกแบบ RESTful ที่สุดเท่าที่จะเป็นไปได้ในขณะเดียวกันก็ทำให้แน่ใจได้ว่าฉันกำลังรักษาข้อ จำกัด ของ HTTP ไว้การออกแบบที่เหมาะสมที่สุดสำหรับการค้นหาคืออะไร


3
ฉันมักจะเจตนาที่จะใช้GET domain/Jobs?keyword={keyword}มันใช้งานได้ดีสำหรับฉัน :) ความหวังของฉันคือว่าSEARCHคำกริยาจะกลายเป็นมาตรฐาน programmers.stackexchange.com/questions/233158/…
Knerd

ใช่ฉันเห็นได้ว่าสำหรับตัวอย่างเล็กน้อยนั้นไม่มีปัญหา แต่ในเครื่องมือที่เรากำลังสร้างมันไม่จริงที่ไม่น่าเชื่อว่าเราจะจบลงด้วยการค้นหาที่ซับซ้อนซึ่งส่งผลให้สตริง GET ยาวกว่า 2000 ตัวอักษร ถ้าเช่นนั้นจะเป็นอย่างไร
Rob Baillie

จริงๆแล้วเป็นจุดที่ดีมาก สิ่งที่เกี่ยวกับการระบุเทคโนโลยีการบีบอัด?
Knerd

2
GET ที่มีเนื้อหาได้รับอนุญาตจากสเปค HTTP อาจหรืออาจไม่ได้รับการสนับสนุนโดยมิดเดิลแวร์ (บางครั้งไม่);) และไม่ได้รับการสนับสนุนเป็นวิธีปฏิบัติ สิ่งนี้เกิดขึ้นกับ Stackexchange เป็นระยะ stackoverflow.com/questions/978061/http-get-with-request-body
Rob

2
ฉันลงเอยด้วยการใช้ POST JobSearch สร้างเอนทิตีการค้นหาจริงและส่งคืน jobSearchId GET jobs? jobSearch = jobSearchId ส่งคืนคอลเล็กชันงานจริง
Cerad

คำตอบ:


93

คุณไม่ควรลืมว่าคำขอGETมีข้อดีเหนือกว่าโซลูชันอื่น ๆ :

1) คำขอ GET สามารถคัดลอกได้จากแถบ URL ซึ่งถูกย่อยโดยเครื่องมือค้นหาซึ่งเป็น "มิตร" อยู่ที่ไหน "เป็นมิตร" หมายความว่าปกติGET คำขอไม่ควรปรับเปลี่ยนอะไรภายในโปรแกรมของคุณ (idempotent) นี่เป็นกรณีมาตรฐานสำหรับการค้นหา

2) แนวคิดทั้งหมดนี้มีความสำคัญมากไม่เพียง แต่จากผู้ใช้และเครื่องมือค้นหา แต่ยังมาจากจุดยืนการออกแบบ API

3) ถ้าคุณสร้างวิธีแก้ปัญหาด้วยPOST / PUTคุณจะมีปัญหาที่คุณไม่ได้คิดในตอนนี้ ตัวอย่างเช่นในกรณีของเบราว์เซอร์ปุ่มย้อนกลับ / รีเฟรชหน้า / ประวัติ แน่นอนว่าสิ่งเหล่านี้สามารถแก้ไขได้ แต่สิ่งนี้จะเป็นวิธีแก้ปัญหาอีกวิธีหนึ่งและอีก ...

พิจารณาทั้งหมดนี้คำแนะนำของฉันจะเป็น:

ก)คุณควรจะสามารถให้พอดีภายในของคุณGET ที่ใช้โครงสร้างพารามิเตอร์ฉลาด ในกรณีที่รุนแรงคุณสามารถใช้กลยุทธ์เช่นการค้นหา google นี้ซึ่งฉันตั้งค่าพารามิเตอร์จำนวนมากยังคงเป็น URL ที่สั้นมาก

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


ส่วนตัวผมจะพยายามที่จะต่อสู้กับทุกกรงเล็บของฉันจะได้รับมันทำกับก)และเมื่อความหวังทั้งหมดจะหายไปผมจะรวบรวมข้อมูลกลับมาพร้อมกับน้ำตาในดวงตาของฉันไปที่ตัวเลือกข)


4
เพื่อความกระจ่างคำถามนี้มีวัตถุประสงค์เพื่อเกี่ยวกับการออกแบบบริการเว็บไม่ใช่การออกแบบเว็บไซต์ ดังนั้นในขณะที่พฤติกรรมของเบราว์เซอร์มีความสนใจในขอบเขตที่กว้างขึ้นของการตีความของคำถามในกรณีเฉพาะที่อธิบายว่าไม่มีผลใด ๆ (ประเด็นที่น่าสนใจ)
Rob Baillie

@RobBaillie Ye เบราว์เซอร์เป็นเพียงกรณีการใช้งาน ฉันต้องการแสดงข้อเท็จจริงที่ว่าการค้นหาโดยรวมของคุณแสดงด้วยสตริง URL ซึ่งมีความสะดวกสบายมากในการใช้งานพร้อมกับจุดอื่น ๆ ในภายหลังในคำตอบ
p1100i

ในจุด b นี่คือการเปลี่ยนแปลงที่เรียบง่ายของการอ้างอิงของฉันเองกับPOSTถึงdomain/Jobs/Search/อาจจะใช้domain/JobsSearch/แทนหรือคุณหมายถึงบางสิ่งที่แตกต่างกันหรือไม่? คุณช่วยอธิบายได้ไหม
Rob Baillie

7
เหตุใดฉันจึงได้รับความประทับใจว่า REST มักเป็นส่วนหนึ่งของปัญหาแทนที่จะเป็นส่วนหนึ่งของวิธีแก้ปัญหา
JensG

1
"คำขอ GET ไม่ควรแก้ไขอะไรในแอปพลิเคชันของคุณ (idempotent)" ในขณะที่ GET นั้นเป็น idempotent คำที่เกี่ยวข้องก็คือ " ปลอดภัย " ที่นี่ Idempotent หมายความว่าการทำ GET บนทรัพยากรสองครั้งนั้นเหมือนกับการทำ GET บนทรัพยากรนั้นครั้งเดียว ตัวอย่างเช่น PUT นั้นเป็น idempotent แต่ก็ไม่ปลอดภัยเช่นกัน
Jasmijn

12

TL; DR: GET สำหรับการกรอง POST สำหรับการค้นหา

ฉันสร้างความแตกต่างระหว่างการกรองผลลัพธ์จากรายการคอลเลกชันและการค้นหาที่ซับซ้อน การทดสอบสารสีน้ำเงินที่ฉันใช้นั้นโดยทั่วไปถ้าฉันต้องการมากกว่าการกรอง(บวกลบหรือช่วง)ฉันคิดว่าเป็นการค้นหาที่ซับซ้อนมากขึ้นซึ่งต้องใช้ POST

สิ่งนี้มีแนวโน้มที่จะได้รับการเสริมเมื่อคิดถึงสิ่งที่จะได้รับคืน ฉันมักจะใช้เพียงได้รับหากทรัพยากรมีส่วนใหญ่ที่สมบูรณ์วงจรชีวิต(PUT ลบ GET, คอลเลกชัน GET) โดยทั่วไปในคอลเล็กชัน GET ฉันจะส่งคืนรายการของ URIs ซึ่งเป็นทรัพยากร REST ที่ประกอบขึ้นเป็นคอลเล็กชันนั้น ในแบบสอบถามที่ซับซ้อนฉันอาจดึงจากหลายแหล่งข้อมูลเพื่อสร้างการตอบสนอง(คิดว่าเข้าร่วม SQL)ดังนั้นฉันจะไม่ส่ง URIs กลับคืน แต่เป็นข้อมูลจริง ปัญหาคือข้อมูลจะไม่ถูกแสดงในแหล่งข้อมูลดังนั้นฉันจะต้องส่งคืนข้อมูลเสมอ นี่เป็นกรณีที่ชัดเจนสำหรับฉันที่ต้องการ POST

-

มันไม่นานมานี้และโพสต์ดั้งเดิมของฉันค่อนข้างเลอะเทอะดังนั้นฉันคิดว่าฉันจะอัปเดต

GET เป็นตัวเลือกที่ใช้งานง่ายสำหรับการส่งคืนข้อมูลส่วนใหญ่การรวบรวมทรัพยากร REST ข้อมูลที่มีโครงสร้างของทรัพยากรแม้แต่เพย์โหลดแบบเอกพจน์ (รูปภาพเอกสาร ฯลฯ )

POST เป็นวิธี catchall สำหรับสิ่งที่ดูเหมือนจะไม่พอดีภายใต้ GET, PUT, DELETE ฯลฯ

ณ จุดนี้ฉันคิดว่าการค้นหาง่าย ๆ การกรองทำให้เข้าใจได้ง่ายผ่าน GET การค้นหาที่ซับซ้อนนั้นขึ้นอยู่กับความชอบส่วนบุคคลโดยเฉพาะอย่างยิ่งถ้าคุณกำลังทำฟังก์ชั่นการรวมตัว, ความสัมพันธ์ข้าม (รวม), การจัดรูปแบบใหม่, ฯลฯ ฉันจะโต้แย้งว่าพารามิเตอร์ของ GET ไม่ควรยาวเกินไป ) มักจะเหมาะสมกว่าในฐานะที่เป็นเนื้อหาคำขอ POST

ฉันพิจารณาแง่มุมประสบการณ์ของการใช้ API ด้วย โดยทั่วไปฉันต้องการใช้วิธีการให้เป็นประโยชน์มากที่สุดและง่ายที่สุด ฉันจะกดการโทรที่มีความยืดหยุ่นมากขึ้น (และซับซ้อนยิ่งขึ้น) ลงใน POST และใน URI ทรัพยากรอื่นโดยเฉพาะอย่างยิ่งถ้ามันไม่สอดคล้องกับพฤติกรรมของทรัพยากร REST อื่น ๆ ใน API เดียวกัน

ไม่ว่าจะด้วยวิธีใดความสอดคล้องอาจมีความสำคัญมากกว่าการค้นหาใน GET หรือ POST

หวังว่านี่จะช่วยได้


1
เนื่องจาก REST มีจุดประสงค์ที่จะแยกการใช้งานพื้นฐาน (เช่น - ทรัพยากรไม่จำเป็นต้องเป็นแถวในฐานข้อมูลหรือไฟล์บนฮาร์ดไดรฟ์ แต่อาจเป็นอะไรก็ได้ ) ฉันไม่ทราบว่าจำเป็นต้องใช้ POST มากกว่า รับเมื่อมันมาถึงการดำเนินการเข้าร่วม SQL สมมติว่าคุณมีโต๊ะของโรงเรียนและโต๊ะของเด็กและคุณต้องการชั้นเรียน (หนึ่งโรงเรียน, เด็กหลายคน) GET /class?queryParamsคุณสามารถจะกำหนดทรัพยากรที่เสมือนจริงและ จากมุมมองของผู้ใช้ "คลาส" นั้นเป็นเรื่องเสมอและคุณไม่จำเป็นต้องทำ SQL แปลก ๆ เข้าร่วม
stevendesu

ไม่มีความแตกต่างระหว่าง "การกรอง" และ "การค้นหา"
Nicholas Shanks

1
ใช่มีตัวกรองจะขึ้นอยู่กับเขตข้อมูลที่มีอยู่ การค้นหาอาจมีรูปแบบที่ซับซ้อนมากขึ้นรวมเขตข้อมูลการคำนวณค่า adjecent ฯลฯ
13796

@stevendesu ตรงนั้นเป็นเหตุผลที่ฉันใช้ POST สำหรับทั้งสอง (สร้างการค้นหา) :-)
ymajoros

@ymajoros ยกเว้นว่าคุณบันทึกข้อความค้นหาและผลลัพธ์ของการค้นหาอยู่ที่ไหนสักแห่งฉันไม่รู้ว่า POST มีความหมาย เมื่อคุณทำการค้นหาที่คุณร้องขอข้อมูลคุณจะไม่ให้ข้อมูลใหม่ที่จะเก็บไว้ที่ใดก็ได้
stevendesu

10

ใน REST นิยามทรัพยากรนั้นกว้างมาก อย่างไรก็ตามคุณต้องการรวมข้อมูลบางส่วนเข้าด้วยกัน

  • การคิดว่าทรัพยากรการค้นหาเป็นทรัพยากรการรวบรวมนั้นมีประโยชน์ บางครั้งพารามิเตอร์การสืบค้นซึ่งบางครั้งเรียกว่าส่วนที่สามารถค้นหาได้ของ URI ทำให้ทรัพยากรแคบลงจนถึงรายการที่ลูกค้าสนใจ

ตัวอย่างเช่น Google URI หลักชี้ไปที่แหล่งรวบรวมของ "ลิงก์ไปยังทุกไซต์บนอินเทอร์เน็ต" พารามิเตอร์การค้นหาแคบลงสำหรับเว็บไซต์ที่คุณต้องการดู

(URI = ตัวระบุทรัพยากรสากลซึ่ง URL = ตัวระบุทรัพยากรสากลโดยที่ "http: //" ที่คุ้นเคยเป็นรูปแบบเริ่มต้นสำหรับ URI ดังนั้น URL จึงเป็นตัวระบุตำแหน่ง แต่ใน REST จะเป็นการดีที่จะพูดคุยกับตัวระบุทรัพยากร แม้ว่าผู้ใช้จะใช้แทนกันได้)

  • เนื่องจากทรัพยากรที่คุณค้นหาในตัวอย่างของคุณคือคอลเล็กชันงานจึงเหมาะสมที่จะค้นหา

รับไซต์ / งาน? type = blah & location = ที่นี่ & ฯลฯ = ฯลฯ

(ส่งคืน) {jobs: [{job: ... }]}}

จากนั้นใช้ POST ซึ่งเป็นภาคผนวกหรือประมวลผลคำกริยาเพื่อเพิ่มรายการใหม่ไปยังคอลเลกชัน:

เว็บไซต์ POST / งาน

{job: ... }

  • โปรดทราบว่ามันเป็นโครงสร้างเดียวกันสำหรับjobวัตถุในแต่ละกรณี ไคลเอนต์สามารถรับชุดของงานใช้ params แบบสอบถามเพื่อ จำกัด การค้นหาและจากนั้นใช้รูปแบบเดียวกันสำหรับรายการใดรายการหนึ่งเพื่อ POST งานใหม่ หรืออาจใช้รายการใดรายการหนึ่งเหล่านั้นแล้วใส่ลงใน URI เพื่ออัปเดตรายการนั้น

  • สำหรับสตริงการสืบค้นที่ยาวหรือซับซ้อนจริง ๆ การประชุมทำให้การส่งแบบคำขอ POST นั้นเป็นเรื่องปกติ รวมเคียวรีพารามิเตอร์ไว้เป็นคู่ชื่อ / ค่าหรืออ็อบเจ็กต์ที่ซ้อนกันในโครงสร้าง JSON หรือ XML และส่งในเนื้อความของคำร้องขอ ตัวอย่างเช่นหากแบบสอบถามของคุณมีข้อมูลซ้อนกันแทนที่จะเป็นคู่ของชื่อ / ค่าจำนวนมาก ข้อมูลจำเพาะ HTTP สำหรับ POST อธิบายว่าเป็นการผนวกหรือประมวลผลคำกริยา (หากคุณต้องการแล่นเรือประจัญบานผ่านช่องโหว่ใน REST ให้ใช้ POST)

ฉันจะใช้มันเป็นแผนสำรอง

สิ่งที่คุณสูญเสียเมื่อทำเช่นนั้นคือก) GET เป็นโมฆะ - คือไม่เปลี่ยนอะไรเลย - โพสต์ไม่ได้ ดังนั้นหากการโทรล้มเหลวมิดเดิลแวร์จะไม่ลองหรือแคชผลลัพธ์โดยอัตโนมัติและ 2) ด้วยพารามิเตอร์การค้นหาในเนื้อหาคุณจะไม่สามารถตัดและวาง URI ได้อีกต่อไป นั่นคือ URI ไม่ใช่ตัวระบุเฉพาะสำหรับการค้นหาที่คุณต้องการ

หากต้องการความแตกต่างระหว่าง "สร้าง" จาก "ค้นหา" มีสองตัวเลือกที่สอดคล้องกับแนวปฏิบัติ REST:

  • คุณสามารถทำได้ใน URI โดยการเพิ่มบางอย่างลงในชื่อของคอลเลกชันเช่นการค้นหางานแทนที่จะเป็นงาน นั่นหมายถึงคุณกำลังปฏิบัติต่อคอลเลกชันการค้นหาเป็นทรัพยากรแยก

  • เนื่องจากความหมายของ POST เป็นทั้งผนวกหรือดำเนินการคุณสามารถระบุหน่วยการค้นหาด้วยส่วนของข้อมูล ชอบ {job: ... } กับ {search: ... } มันขึ้นอยู่กับตรรกะ POST เพื่อโพสต์หรือประมวลผลอย่างเหมาะสม

นั่นเป็นการออกแบบ / การนำไปใช้งานที่ค่อนข้างดี ฉันไม่คิดว่าจะมีการประชุมที่ชัดเจน

ดังนั้นเช่นเดียวกับที่คุณได้กำหนดไว้แล้วความคิดคือการกำหนดทรัพยากรการรวบรวมสำหรับ jobs

เว็บไซต์ / งาน

ค้นหาด้วย GET + params การสืบค้นเพื่อ จำกัด การค้นหา การสืบค้นข้อมูลที่มีโครงสร้างยาวหรือมีโครงสร้างจะเข้าสู่เนื้อหาของ POST (อาจเป็นไปได้ในการรวบรวมการค้นหาแยกต่างหาก) สร้างด้วย POST เพื่อผนวกเข้ากับคอลเล็กชัน และอัปเดตด้วย PUT เป็น URI ที่เฉพาะเจาะจง

(FWIW รูปแบบการประชุมกับ URIs คือการใช้ตัวพิมพ์เล็กทั้งหมดที่มีคำคั่นด้วยเครื่องหมายยัติภังค์ แต่นั่นไม่ได้หมายความว่าคุณต้องทำแบบนั้น)

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


มันเป็นความคิดที่น่าสนใจ - ฉันจะไม่พิจารณาเรื่องการใช้เพย์โหลดเพื่อแยกความแตกต่าง ดูเหมือนว่าจะมีเล่ห์เหลี่ยมเล็กน้อย! แต่ฉันเดาว่ารูปแบบ URI ไม่มีคำกริยาใด ๆ - เป็นประเภทคำขอที่กำหนดคำกริยา บางทีเพย์โหลดอาจจะใกล้เคียงกับประเภทคำขอมากกว่า URI ข้อกังวลเพียงอย่างเดียวคือ - ผู้ใช้ API นั้นโปร่งใสหรือไม่
Rob Baillie

ในแง่ของการใช้งาน (เรากำลังใช้ Node และ Express) มันอาจหมายถึงว่าrouteไม่สามารถจัดการกับทางเลือกของการประมวลผลได้ ฉันจะต้องดูที่ ...
Rob Baillie

ฉันมีความรู้สึกเหมือนกันว่าการแยกมันด้วย URI นั้นดูสะอาดกว่า ฉันจะกลับไปกลับมา มันเป็นสายการตัดสิน อย่างไรก็ตามความหมายของ HTTP จะอนุญาตให้วางไว้ในเนื้อหา ฉันอยากจะบอกว่า REST นั้นเป็นแบบอย่างหลังจาก World Wide Web และ WWW นั้นถูกสร้างด้วย GET และ POST
Rob

8

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

คุณสามารถใช้ราชสกุลเช่น$select=และ$filter=ดังนั้นคุณจะจบลงด้วย URI ซึ่งมีลักษณะบางอย่างเช่นนี้

/users?$select=Id,Name$filter=endswith(Name, 'Smith')

คุณสามารถทำเพจจิ้งโดยใช้$skipและ$topและการสั่งซื้อ

สำหรับข้อมูลเพิ่มเติมโปรดดูที่OData.org คุณไม่ได้ระบุภาษาที่คุณใช้ แต่ถ้าเป็น ASP.NET แพลตฟอร์ม WebApi รองรับการสืบค้น OData - สำหรับผู้อื่น (PHP ฯลฯ ) อาจมีห้องสมุดที่คุณสามารถใช้ในการแปลเป็นแบบสอบถามฐานข้อมูล


6
ลิงก์ที่น่าสนใจและน่าดู แต่มันแก้ปัญหาพื้นฐานที่อธิบายได้หรือไม่ว่าการร้องขอของ GET นั้นไม่รองรับอักขระมากกว่า 2000 ตัวในสตริงการสืบค้นและเป็นไปได้ทั้งหมดที่แบบสอบถามอาจยาวกว่านี้หรือไม่
Rob Baillie

@RobBaillie ฉันไม่คิดอย่างนั้นเพราะมันยังคงได้รับการโทรด้วยสตริงแบบสอบถาม ฉันขอแนะนำให้ใช้ OData ทุกที่ที่คุณทำได้เนื่องจากเป็นมาตรฐานสำหรับการสืบค้นแหล่งข้อมูลบนเว็บและสำหรับบางครั้ง (ถ้ามี) เวลาที่การสืบค้นต้องซับซ้อนมากจนคุณไม่สามารถใส่ลงในแบบสอบถามแบบอักขระ 2000 ได้ให้สร้างเฉพาะ จุดสิ้นสุดที่คุณโทรไปหา
Trevor Pilley

คุณสามารถอธิบายวิธีการของคุณสำหรับ "ปลายทางเฉพาะที่คุณโทรไปหา" ได้หรือไม่? คุณอาจจินตนาการถึงจุดสิ้นสุดที่จะเป็นอย่างไร
Rob Baillie

@RobBaillie แน่นอน - อีกครั้งฉันไม่แน่ใจว่าเทคโนโลยีที่คุณใช้อยู่ แต่ใน ASP.NET ฉันจะสร้างตัวควบคุมเฉพาะที่เรียกว่าJobsNearMeAddedInTheLast7Daysหรืออะไรก็ตามที่จะแค็ปซูลเคียวรีที่ยาวเกินไป / ซับซ้อนสำหรับ OData แล้วเปิดเผยผ่านการโทร GET เท่านั้น .
Trevor Pilley

1
ฉันเห็น. ความคิดที่น่าสนใจอีกอย่างที่อาจมีขาบ้าง แต่ฉันไม่แน่ใจว่าสิ่งนี้จะช่วยได้ในกรณีเฉพาะของฉัน - การค้นหาที่มีหลายแง่มุมและหลายแง่มุมที่เป็นไปได้
Rob Baillie

5

/jobs/filtersวิธีการหนึ่งที่จะต้องพิจารณาคือการรักษาชุดของคำสั่งที่เป็นไปได้เป็นทรัพยากรที่มีคอลเลกชันเช่น

POSTการร้องขอไปยังทรัพยากรนี้มีพารามิเตอร์แบบสอบถามในร่างกายอย่างใดอย่างหนึ่งจะสร้างทรัพยากรใหม่หรือระบุตัวกรองเทียบเท่าที่มีอยู่และกลับ URL ที่มี ID /jobs/filters/12345ที่:

รหัสนั้นจะสามารถใช้ในคำขอ GET /jobs?filter=12345สำหรับงาน: GETคำขอที่ตามมาในทรัพยากรตัวกรองจะส่งกลับคำจำกัดความของตัวกรอง

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

ข้อเสียเปรียบสำหรับวิธีนี้คือการที่คุณสูญเสียความสามารถในการอ่าน URL (แม้ว่าวิธีนี้สามารถบรรเทาได้ด้วยการดึงคำจำกัดความแม้ว่าการGETร้องขอสำหรับทรัพยากรตัวกรอง) ด้วยเหตุผลนี้คุณอาจต้องการสนับสนุนพารามิเตอร์คิวรีเดียวกันหรือชุดย่อยบน/jobsทรัพยากรที่คุณจะสนับสนุนทรัพยากรตัวกรอง สามารถใช้สำหรับการสืบค้นที่สั้นกว่านี้ได้ หากคุณลักษณะนี้มีให้เพื่อรักษา cacheability ระหว่างสองประเภทของการกรองเมื่อใช้พารามิเตอร์การค้นหาบน/jobsทรัพยากรการดำเนินงานภายในควรสร้าง / นำมาใช้ทรัพยากรกรองและส่งกลับ302หรือ303สถานะที่ระบุ URL /jobs?filter=12345ในรูปแบบของ


ปฏิกิริยาแรกของฉันต่อสิ่งนี้คือในขณะที่มันเป็นข้อมูลที่ดีจริงๆมันเป็นเพียงความแตกต่างของคำตอบที่ได้รับจาก @burninggramma โดยพื้นฐานแล้วมันคือ "สร้างเอนทิตีใหม่ที่เรียกว่าตัวกรอง / การค้นหาโทรเพื่อสร้างและจากนั้นเรียกเพื่อเรียกคืน" รูปแบบที่การเรียกเพื่อเรียกคืนนั้นเป็นเหมือนการเรียกเพื่อใช้กับคอลเลกชัน น่าสนใจ อย่างไรก็ตามคำตอบของคุณและการเขียนโปรแกรมประสบปัญหาเดียวกัน - ฉันไม่มีความปรารถนาที่จะสร้างตัวกรอง จะมีพวกเขาจำนวนมากและพวกเขาไม่จำเป็นต้องจัดเก็บยกเว้นเพื่อให้การใช้งานสงบ
Rob Baillie

2
เห็นได้ชัดว่าพารามิเตอร์การสืบค้นเป็นทางออกที่ดีที่สุด แต่คำถามของคุณจะถามเฉพาะเกี่ยวกับวิธีจัดการกับคำจำกัดความตัวกรองยาวกว่าขีด จำกัด ของ URL ที่เซิร์ฟเวอร์บางแห่งกำหนด เพื่อหลีกเลี่ยงการจำกัดความยาวคุณจะต้องบีบอัดสตริงการค้นหาอย่างใดอย่างหนึ่งหรือคุณต้องใช้วิธีการร้องขอที่รองรับการระบุเนื้อหาของความยาวโดยพลการ หากคุณไม่ต้องการใช้ตัวกรองเป็นทรัพยากรให้รองรับอินเทอร์เฟซที่ไม่ได้พักผ่อนซึ่งมีการกำหนดตัวกรองไว้ คุณจะสูญเสียความสามารถในการแคช แต่ถ้าข้อมูลของคุณมีความผันผวนเพียงพอก็จะไม่ได้รับประโยชน์จากการแคช
pgraham

คุณสามารถเอาชนะความต้องการในการจัดเก็บตัวกรองได้โดย ... ไม่เก็บไว้ ไม่มีอะไรเกี่ยวกับ REST รับประกันได้ว่าเป็นแบบถาวร คุณอาจร้องขอGET /jobs/37และรับผลลัพธ์จากนั้นมีคนลบทรัพยากรและ 2 วินาทีต่อมาคำขอเดียวกันส่งคืน 404 ในทำนองเดียวกันถ้าคุณPOST /searchesและคุณถูกเปลี่ยนเส้นทางไปยังผลลัพธ์การค้นหา (การค้นหาถูกสร้างขึ้นและคุณได้รับ 201 ด้วย ตำแหน่งส่วนหัวของทรัพยากร) 2 วินาทีหลังจากนั้นผลลัพธ์อาจถูกลบออกจากหน่วยความจำและจะต้องสร้างใหม่ ไม่จำเป็นต้องมีที่เก็บข้อมูลระยะยาว
stevendesu

5

นี่เป็นคำตอบเก่า ๆ แต่ฉันก็ยังมีส่วนร่วมในการอภิปรายเล็กน้อย ฉันสังเกตเห็นบ่อยครั้งเกี่ยวกับความเข้าใจผิดของ REST, RESTful และ Architecture RESTful ไม่เคยพูดถึงสิ่งใดเกี่ยวกับการไม่สร้างการค้นหาไม่มีสิ่งใดใน RESTful เกี่ยวกับสถาปัตยกรรมมันเป็นชุดของหลักการหรือเกณฑ์การออกแบบ

เพื่ออธิบายการค้นหาในวิธีที่ดีกว่าเราต้องพูดถึงสถาปัตยกรรมโดยเฉพาะและสิ่งที่เหมาะสมยิ่งขึ้นคือสถาปัตยกรรมเชิงทรัพยากร (ROA)

ใน RESTful มีหลักการในการออกแบบ idempotent ไม่ได้หมายความว่าผลลัพธ์ไม่สามารถเปลี่ยนแปลงได้เมื่อฉันอ่านคำตอบบางอย่างมันหมายถึงผลลัพธ์ของการร้องขอที่เป็นอิสระไม่ได้ขึ้นอยู่กับการดำเนินการหลายครั้ง มันสามารถเปลี่ยนแปลงได้สมมติว่าฉันอัปเดตฐานข้อมูลอย่างต่อเนื่องด้วยข้อมูลบางส่วนที่ให้บริการโดย RESTful Api การดำเนินการ GET เดียวกันอาจเปลี่ยนผลลัพธ์ แต่ไม่ได้ขึ้นอยู่กับว่ามีการดำเนินการกี่ครั้ง หากฉันสามารถตรึงโลกได้ก็หมายความว่าไม่มีสถานะการเปลี่ยนแปลงอะไรในบริการเมื่อฉันขอทรัพยากรที่นำไปสู่ผลลัพธ์ที่แตกต่าง

ตามนิยามแล้วทรัพยากรคือสิ่งใดก็ตามที่มีความสำคัญต่อการอ้างอิงด้วยตนเอง

ในสถาปัตยกรรมที่มุ่งเน้นทรัพยากร (เรียกว่า ROA จากนี้ไปเพื่อความกะทัดรัด) เรามุ่งเน้นไปที่ทรัพยากรที่อาจมีหลายสิ่ง:

  • เวอร์ชันของเอกสาร
  • เอกสารเวอร์ชันที่อัปเดตล่าสุด
  • ผลลัพธ์ที่ได้จากการค้นหา
  • รายการของวัตถุ
  • บทความแรกที่ฉันซื้อจากอีคอมเมิร์ซ

สิ่งที่ทำให้มันโดดเด่นในแง่ของทรัพยากรคือความสามารถในการเพิ่มซึ่งหมายความว่ามันมีURI เพียงอันเดียว

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

คุณสามารถค้นหาหลักการของสิ่งที่แน่นอนและ URI ในเอกสารต้นฉบับ W3:

https://www.w3.org/DesignIssues/Axioms

URL ใด ๆ ในสถาปัตยกรรมนี้ต้องอธิบายด้วยตนเอง จำเป็นถ้าคุณทำตามหลักการเพื่อจัดการทุกสิ่งใน URI นั่นหมายความว่าคุณสามารถใช้ / (สแลช) เพื่อแยกสิ่งที่คุณต้องการหรือพารามิเตอร์การสืบค้น เรารู้ว่ามีข้อ จำกัด ในเรื่องนี้ แต่นี่เป็นรูปแบบสถาปัตยกรรม

ตามรูปแบบ ROA ใน RESTful การค้นหาไม่ได้เป็นมากกว่าทรัพยากรอื่น ๆ ความแตกต่างเพียงอย่างเดียวคือทรัพยากรมาจากการคำนวณแทนความสัมพันธ์โดยตรงกับวัตถุเอง ตามหลักการฉันสามารถจัดการและรับบริการการคำนวณทางคณิตศาสตร์อย่างง่ายตามรูปแบบต่อไปนี้:

http://myapi.com/sum/1/2

โดยที่ผลรวม 1 และ 2 สามารถปรับเปลี่ยนได้ แต่ผลลัพธ์ของการคำนวณนั้นไม่ซ้ำกันและมัน adressable ทุกครั้งที่ฉันเรียกด้วยพารามิเตอร์เดียวกันที่ฉันได้รับเหมือนกันและไม่มีอะไรเปลี่ยนแปลงในบริการ resouce / sum / 1/2 และ / substract / 5/4 ติดกับหลักการอย่างสมบูรณ์แบบ


3

GET นั้นโอเคถ้าคุณมีการรวบรวมแบบสแตติกที่ส่งคืนผลลัพธ์เดียวกัน (การแสดง) สำหรับ URI เดียวเสมอ นั่นก็หมายความว่าข้อมูลที่สร้างการรับรองเหล่านี้จะไม่เปลี่ยนแปลง แหล่งที่มาเป็นฐานข้อมูลแบบอ่านอย่างเดียว

มีผลลัพธ์ที่แตกต่างได้รับผลตอบแทนสำหรับหนึ่งและ URI เดียวกันละเมิดIdempotency / ความปลอดภัยและหลักการ CoolURIและเป็นจึงไม่สงบ เป็นไปได้ที่จะมีกริยา idempotent เขียนไปยังฐานข้อมูล แต่จะต้องไม่ส่งผลกระทบต่อการแทน

การค้นหาทั่วไปเริ่มต้นด้วยคำขอ POST ที่ส่งคืนการอ้างอิงถึงผลลัพธ์ มันสร้างผลลัพธ์ (มันเป็นเรื่องใหม่และสามารถเรียกได้ด้วย GET ที่ตามมา) ผลลัพธ์นี้อาจเป็นลำดับชั้น (อ้างอิงเพิ่มเติมกับ URIs ที่คุณสามารถรับได้) แน่นอนและอาจนำองค์ประกอบของการค้นหาก่อนหน้านี้มาใช้ใหม่หากเหมาะสมสำหรับแอปพลิเคชัน

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


Aaaaaaaah - นั่นคือวิธีการทำงาน! ขอบคุณ!
Rob Baillie

1
Idempotency ไม่ได้หมายความว่ามันจะต้องกลับมาเหมือนเดิมทุกครั้งมันจะต้องกลับมาเหมือนเดิมหากไม่มีอะไรเปลี่ยนแปลง การค้นหาถือได้ว่าเป็นผลลัพธ์ของการคำนวณและเป็นทรัพยากรเอง
Maximiliano Rios

Idempotency จริง ๆ แล้วหมายความว่าผลลัพธ์ยังคงเหมือนเดิม คุณสามารถและเป็นไปได้ที่จะใช้การควบคุมแคช และแน่นอนคุณสามารถใช้ DELETE ที่รบกวน GETs ในภายหลัง อย่างไรก็ตามหากตัวแทนต้องการให้ความรู้เกี่ยวกับการทำงานภายในของแอปพลิเคชันมันจะไม่สงบ ข้างต้นฉันกำลังพูดถึงความคิดที่รุนแรงที่สุดของ REST ในทางปฏิบัติผู้คนสามารถละเมิดหลายแง่มุมของมัน พวกเขาจ่ายราคาเมื่อแคชไม่แคชอย่างมีประสิทธิภาพอีกต่อไป
Martin Sugioarto

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