วิธีที่เหมาะสมในการทำวิธีการค้นหาแบบ RESTful ที่ซับซ้อนคืออะไร


44

ตามหลักการ REST ฉันต้องการสร้างวิธีการ GET สำหรับ API ของฉันที่ทำการค้นหาโดยใช้เกณฑ์บางอย่างและส่งคืนผลลัพธ์ให้กับลูกค้า ปัญหาคือเกณฑ์สามารถมีพารามิเตอร์ได้มากถึง 14 พารามิเตอร์โดยหนึ่งในนั้นคือรายการของวัตถุที่ซับซ้อนดังนั้น ...

  • ฉันไม่รู้ด้วยซ้ำว่าเป็นไปได้ในการเข้ารหัส / ถอดรหัสวัตถุที่ซับซ้อนเหล่านี้ไปยัง / จากพารามิเตอร์ url

  • ฉันไม่ได้คำนวณระยะเวลาที่ URL จะได้รับ แต่ฉันแน่ใจว่ามันจะมีขนาดใหญ่พอและอาจถึงขีด จำกัด ของ URL ได้หรือไม่

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

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


3
นอกเหนือจาก (ฉันทราบว่าทั้งสองคำตอบในขณะที่เขียนพูดถึงส่วนเวลาจริง) โดยทั่วไปการค้นหาตามเวลาจริงควรเป็นเพียงแค่ส่งคำขอที่อัปเดตซ้ำแล้วซ้ำอีก เช่นในขณะที่คุณกำลังพิมพ์คุณต้องการจะส่งการร้องขอสำหรับสิ่งที่ชอบsearch?q=t, search?q=te, search?q=testและอื่น ๆ พิจารณา จำกัด ความถี่ในการส่งแบบสอบถามเพื่อหลีกเลี่ยงการทำร้ายเซิร์ฟเวอร์ของคุณ นอกจากนี้คุณยังสามารถส่งคืนข้อมูลจำนวนมากและในด้านลูกค้าทำการกรอง ใช้งานได้ดีหากผู้ใช้เข้าสู่หมวดหมู่ทั่วไปที่สามารถ จำกัด สิ่งต่าง ๆ ลงได้อย่างมาก
Kat

2
ไม่ว่าจะเป็นการแก้ปัญหาให้แน่ใจว่าได้แลกเปลี่ยนข้อมูลในรูปแบบที่เป็นกลางทางเทคโนโลยี ดังนั้นอย่าใช้การเป็นตัวแทนภายในมิฉะนั้นจะเป็นการยากที่จะเขียนไคลเอนต์สำหรับ API ของคุณ
Kwebble

ทั้งนี้ขึ้นอยู่กับความต้องการของคุณห้องสมุดนี้จะทำให้งาน: github.com/jirutka/rsql-parser มีส่วนขยาย JPA หากคุณใช้ JPA หรือคุณสามารถเขียนผู้เยี่ยมชมของคุณเองเพื่อแมปไปยัง API ของเครื่องมือค้นหาของคุณ และคุณสามารถเพิ่มผู้ให้บริการของคุณเอง
Walfrat

คำตอบ:


54

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

อย่างไรก็ตามในคำตอบของนีลฉันก็พลาดไปอีกอย่าง เอกสารประกอบ เพียงเพื่อให้แน่ใจว่านักพัฒนาซอฟต์แวร์ทราบว่า POST ขอ/searchปลอดภัย

ที่กล่าวว่า

1. ให้โอกาสในการรับ

พิจารณาGETตัวเลือกแรก ตรวจสอบคำถามนี้ความยาวสูงสุดของ URL ประเมินว่าสตริงข้อความค้นหาที่ยาวที่สุดของคุณยาวกว่า 2000 ตัวอักษรหรือไม่ GETถ้ามันไม่ได้และคุณไม่ได้คาดหวังว่ามันจะไปกับ มันอาจดูน่าเกลียด แต่อย่างน้อยคุณก็สามารถบุ๊กมาร์ก URL และแน่นอนว่ามันมีข้อดีทั้งหมดที่ได้มาจากความหมายของเมธอด (idempotence, safe and caching)

1.1 ลองเข้ารหัสสตริงแบบสอบถาม

ยกตัวอย่างเช่นในฐาน 64. สนับสนุนแม้จาวาสคริปต์ฐาน 64 เข้ารหัส

นี่คือวิธีการ:

  1. สร้าง JSON ด้วยตัวกรองทั้งหมดและทำให้เป็นมาตรฐาน
  2. แยกมันเป็นสตริง
  3. เข้ารหัสมัน
  4. ส่ง JSON ที่เข้ารหัสเป็นคำขอพารามิเตอร์ ( /search?q=SGVsbG8gV29ybGQh....)
  5. บนฝั่งเซิร์ฟเวอร์, ถอดรหัสพระรามQ
  6. ยกเลิกการทำให้เป็นสตริง JSON

ก่อนหน้านี้สร้างสตริง JSON ที่ยาวที่สุดที่เป็นไปได้เข้ารหัสและใช้ความยาว ประเมินว่าสตริงที่เข้ารหัสนั้นเหมาะสมกับ URL หรือไม่ ฉันใช้ตัวอย่างข้อมูลต่อไปนี้บนFiddle.jsเพื่อให้คุณทดสอบ (ฉันหวังว่ามันจะยังใช้งานได้) 1

การเข้ารหัส Base 64 นั้นสามารถกำหนดค่าได้และสามารถย้อนกลับได้ดังนั้นจึงไม่มีโอกาสเกิดการชน

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

1.2 ลองใช้นามแฝง

เมื่ออ่านบล็อกนี้เกี่ยวกับวิธีออกแบบ REST APIs ฉันจำได้อีกทางเลือกหนึ่ง นามแฝงสำหรับการค้นหาที่พบบ่อย

ฉันคิดว่าสิ่งเหล่านี้น่าสนใจสำหรับเหตุผลต่อไป

  • ย่อความยาวสตริงข้อความค้นหาให้สั้นลง มันทำให้ API สะอาดและใช้งานง่าย

    GET / tickets /? status = closed & closedAt = xxx vs GET / tickets / เพิ่งปิด /

  • ใช้ร่วมกับนามแฝงอื่น ๆ หรือพารามิเตอร์คำขอมากกว่านี้

    GET / tickets /? status = closed & closedAt = xxx & ภายใน = 30 นาที เทียบกับ GET / tickets / / เพิ่งปิด / ภายใน = 30 นาที

  • เราสามารถรวมนามแฝงกับสตริงการสืบค้นที่เข้ารหัส

    GET / tickets /? status = closed & closedAt = xxx & ภายใน = 30 นาที เทียบกับ GET / tickets / ปิดเมื่อเร็ว ๆ นี้ /? q = SGVsbG8g ...


1: ฉันใช้ JSON แล้ว แต่เราสามารถใช้รูปแบบอื่นได้ทันทีที่เราสามารถทำการ deserialize บนฝั่งเซิร์ฟเวอร์ได้


2
นี่เป็นทั้งการปฏิบัติและถูกต้อง นอกจากนี้ยังเป็นที่น่าสังเกตว่าภาษาการเขียนโปรแกรมส่วนใหญ่ทำให้การแปลงแฮชเป็นสตริงการสืบค้นเล็กน้อยดังนั้นการเริ่มต้นด้วยการกระทำของ GET นั้นทำได้ง่ายมาก
Aluan Haddad

1
ฉันชอบ Spring stackoverflow.com/questions/16942193/…ฉันไม่อยากจะเชื่อเลยว่ามันจะใช้งานได้ตั้งแต่ลองครั้งแรก: D เกี่ยวกับ url lenght นั้นมีค่าน้อยกว่า 1k แม้ว่าเราจะยังต้องย้ำ specs
anat0lius

จากนั้นไปกับ GET เพื่อความเรียบง่าย ด้วย Spring MVC คุณสามารถบรรลุการทำแผนที่เดียวกันกับ GET มองหา WebArgumentResolver ฤดูใบไม้ผลิ ;-)
LAIV

Base64 ขยายขนาดของเพย์โหลดประมาณ 4/3 ในขณะที่ urlencoding สามารถทำให้เป็น 3/3 สำหรับตัวอักษรพิเศษแบบสอบถามที่มีตัวละครที่ปลอดภัยส่วนใหญ่จะมีขนาดเท่าเดิม มีเหตุผลอื่นอีกไหมในการใช้ base64?
villasv

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

13

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

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


2
@LiLou_: สำหรับความต้องการนั้นมีความเป็นไปได้เพียงสองประการเท่านั้น: 1. อ่านข้อมูลทั้งหมดไปยังส่วนหน้าของคุณและทำการกรองที่นั่น นี่อาจเป็นสิ่งต้องห้ามในจำนวนหน่วยความจำที่ต้องการ 2. ทำการร้องขอใหม่ไปยังเซิร์ฟเวอร์สำหรับการเปลี่ยนแปลงแต่ละครั้งในเกณฑ์การค้นหา ไม่สำคัญว่านี่จะเป็นการโพสต์หรือคำขอ GET แต่เวลาแฝงของเครือข่ายที่เกี่ยวข้องอาจก่อให้เกิดความเสียหายต่อการรับรู้ของผู้ใช้ในการอัพเดตแบบเรียลไทม์
Bart van Ingen Schenau

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

2
@CodeYogi บางครั้งลูกค้าไม่ได้ให้พื้นที่สำหรับการพูดคุย ฉันใช้หน้าดูแบบ Excel ที่มีคอลัมน์ 40-50 คอลัมน์แต่ละรายการมีตัวกรองของตัวเอง และจัดเรียงแน่นอน ยังไงก็ตาม GET ยังคงเป็นไปได้ แต่มันอาจดูไม่เป็นแฟชั่นเกินไป
Laiv

1
@Laiv ในกรณีนั้นจำเป็นต้องมีการพูดคุยอย่างจริงจังเพราะ POST มีไว้สำหรับการเปลี่ยนแปลงในสถานะเซิร์ฟเวอร์ กรณีการใช้งานเช่นนี้ไม่ได้เป็นข้อยกเว้นดังนั้นจึงควรได้รับการดูแลโดยไม่แฮ็ก
CodeYogi

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

0

มันขึ้นอยู่กับรูปแบบ API ของคุณอย่างเต็มที่: ไม่ว่าจะเป็นหรือคำกริยา

ถ้า API เป็น none คุณอาจต้องการรับรายการของวัตถุดังนี้:

GET: /api/v1/objects

ในกรณีนี้คุณต้องส่งข้อมูลเป็นพารามิเตอร์คำขอ ดังนั้นคุณต้องอธิบายพารามิเตอร์ของคุณเป็นรายการหลักของค่าคีย์:

GET: /api/v1/objects

key1 : val1
key2.key1 : val 21
key2.key2 : val 22
....

บางแพลตฟอร์มรองรับตัวแก้ไขพารามิเตอร์ที่กำหนดเอง (เช่น Spring MVC) คุณสามารถแปลงพารามิเตอร์ให้เป็นวัตถุได้

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