ฉันมีตาราง DynamoDB ชื่อ URLArray ซึ่งมีรายการ URL (myURL) และชื่อวิดีโอที่ไม่ซ้ำกัน (myKey)
ฉันต้องทำสองสิ่ง:
- เมื่อผู้ใช้คลิกปุ่มวิดีโอถัดไป จะต้องเลือกรายการสุ่มจาก URLArray นี้ อาจมีแถวนับหมื่นแถวก็ได้
ผู้ใช้เข้าสู่ระบบแอป ทุกครั้งที่ดูวิดีโอจบ ชื่อวิดีโอเฉพาะของวิดีโอจะถูกบันทึก ดังนั้น....เมื่อผู้ใช้ดูวิดีโอ วิดีโอนั้นจะถูกเพิ่มลงในรายการในตารางชื่อ ผู้ใช้ ใต้แถวข้อมูลของผู้ใช้
- ซู...รายการสุ่มนี้ที่ถูกเลือกเมื่อผู้ใช้คลิกปุ่มวิดีโอถัดไปในจุดที่ 1 จะต้องถูกเปรียบเทียบกับรายการวิดีโอที่พวกเขาได้เห็นแล้ว เพื่อให้แน่ใจว่าจะไม่ปรากฏขึ้นแบบสุ่มอีกครั้งสำหรับผู้ใช้รายนั้น
จนถึงตอนนี้ฉันทำบางอย่างที่ไม่มีประสิทธิภาพมากนัก ซึ่งได้ผล แต่มันก็ไม่ได้ดีนัก:
อย่างไรก็ตาม ฉันใช้ AppSync + GraphQL เพื่อโต้ตอบกับตาราง DynamoDB ฉันได้รับสำเนา URLArray ในเครื่องก่อน:
//Gets a list of the Key/URL pairs in the UrlArrays table in GraphQL ****IN CONSTRUCTOR, so we have this URLArray data when componentDidMount()****
listUrlArrays = async () => {
try {
URLData = await API.graphql(graphqlOperation(ListUrlArrays)); //GraphQL query
//URLData[] is available in the entire class
this.setState({urlArrayLength: apiData.data.listURLArrays.items.length}); //gets the length of URLArray (i.e. how many videos are in the database)
}
}
โดยภาพรวม เมื่อผู้ใช้คลิกเพื่อดูวิดีโอถัดไป:
//When clicking next video
async nextVideo(){
await this.logVideosSeen(); //add myKey to the list of videos in *Users* table the logged in user has now seen
await this.getURL(); //get the NEXT upcoming video's details, for Video Player to play and make sure it's not been seen before
}
//This will update the 'listOfVideosSeen[]' in Users table with videos unique myKey, the logged in user has seen
logVideosSeen = async () => {
.......
}
async getURL() {
var dbIndex = this.getUniqueRandomNumber(this.state.urlArrayLength); //Choose a number between 0 and N number of videos in URLArray
//the hasVideoBeenSeen() basically gets the list of videos a user has already seen from `Users` table with the GraphQL getusers command, and creates a local copy of this list (can get big). I use javascripts indexOf() to check whether myKey already exists in the list
while(await this.hasVideoBeenSeen(this.state.URLData[dbIndex].myKey)) //while true i.e. user has seen that video before
{
dbIndex = this.getUniqueRandomNumber(this.state.urlArrayLength); //get another random number to fetch a new myKey
}
//If false, we'll exit the loop and know we've got a not seen before myKey, proceed to set to play...
if(dbIndex != null){
this.setState({ playURL: this.state.URLData[dbIndex].vidURL }); //Retrieve the URL from the local URLArray that we're going to play (i.e. the next video to come)
}
}
ฉันสามารถแชร์โค้ดเพิ่มเติมได้อีกเล็กน้อยหากจำเป็น แต่โดยพื้นฐานแล้ว ฉันต้องการทราบวิธี:
ให้ฟังก์ชัน Lambda เลือกตัวเลขสุ่มตามขนาด URLArray ปัจจุบัน (ฉันอาจต้องเก็บสำเนา URLArray ในเครื่องไว้อยู่แล้ว) แต่ผมคิดว่าข้อ 2 ที่นี่คือจุดที่มันไม่มีประสิทธิภาพจริงๆ..
ให้ฟังก์ชัน Lambda ตรวจสอบ (ลูป while) กับตาราง Users ว่าเห็น myKey แล้วหรือไม่ โดยหลักแล้วเพื่อเปลี่ยนภาระการคำนวณนี้ไปยังคลาวด์แทนอุปกรณ์ในเครื่องที่แอปทำงานอยู่
หลังจากคิด................
ขอบคุณที่แนะนำเซธ ฉันคิดเรื่องนี้มาระยะหนึ่งแล้ว และแม้ว่าข้อกำหนดการสุ่มยังคงเป็นจริง ฉันคิดว่าสิ่งที่คุณแนะนำก็มีความจริงอยู่บ้าง เหตุผลที่ฉันต้องการการสุ่มก็คือเพื่อให้ผู้ใช้ 2 คนนั่งเคียงข้างกัน ไม่สามารถคาดเดาได้ว่าวิดีโอใดที่กำลังจะมาต่อไป ไม่ควรเป็นลำดับวิดีโอที่คาดเดาได้ ฉันไม่แน่ใจว่าฉันสามารถใช้ฟังก์ชัน Scan
กับ AWS Amplify/GraphQL ได้ ดังนั้นโปรดจำไว้ว่ามี 2 สิ่งที่เกิดขึ้นที่นี่: (1) การอัปโหลดวิดีโอ โดยบันทึกไว้ใน URLArray อย่างสมเหตุสมผลเพื่อใช้อ้างอิงในอนาคต (2) ผู้ใช้ดูวิดีโอสุ่มที่ไม่เคยเห็นมาก่อน จากนั้นจึงย้ายไปยังวิดีโอสุ่มที่มองไม่เห็นอีกรายการหนึ่ง
*(1) ฉันชอบความคิดของคุณในการใช้ตัวเลขเพื่อสร้างดัชนี URLArray และมันช่วยให้ชีวิตง่ายขึ้นนิดหน่อย ดังนั้น URL แรกอยู่ที่ดัชนี 0, ถัดไปที่ 1 ฯลฯ...
ความคิดของฉันที่นี่ (เพื่อหลีกเลี่ยงไม่ให้ฉันทำ ListUrlArrays()
และนำอาเรย์ทั้งหมดมาไว้ในโทรศัพท์) คือการสร้าง GSI ชื่อ VideoNumber
สำหรับตาราง URLArray นี่จะเป็นคอลัมน์ VideoNumber ที่ไม่ซ้ำกันซึ่งมีตัวเลข 0-N ลองจินตนาการถึงแผนภาพด้านบนที่มีคอลัมน์อื่นชื่อ VideoNumber แถว 1 มี VideoNumber ตั้งค่าเป็น 0, แถว 2 มี VideoNumber ตั้งค่าเป็น 1 ฯลฯ... จากนั้นสิ่งที่ฉันต้องทำคืออยู่ในอุปกรณ์ สร้างตัวเลขสุ่มระหว่าง 0-N เรียกใช้แบบสอบถาม getURLArrayIdbyVideoNumber()
เฉพาะสำหรับ GSI นั้น ด้วย หมายเลขที่เราเพิ่งสร้างขึ้น และจะปลดล็อกข้อมูลที่ฉันต้องการจากแถวนั้น เอาล่ะ! ฉันคิดว่านั่นจะช่วยขจัดภาระหนักส่วนใหญ่ออกไปในตอนนี้
คำถาม: ก่อนอัปโหลดวิดีโอแต่ละรายการ ฉันจะรับจำนวนแถว N ทั้งหมดในปัจจุบันในตาราง (หรือจำนวนแถว) ได้อย่างง่ายดายได้อย่างไร จากนั้นฉันก็จะเพิ่มขึ้นทีละหนึ่ง
อีกสิ่งหนึ่งที่ฉันทำได้คือบันทึกหมายเลขการนับปัจจุบันนี้ในตาราง DynamoDB อื่นที่ฉันใช้สำหรับข้อมูลที่มีอยู่ อ่านตัวเลขจากที่นั่นก่อนอัปโหลด และเขียน N+1 หลังจากการอัปโหลดเพื่อเพิ่ม (2 การดำเนินการ DynamoDB ต่อการอัปโหลด) มันไม่เหมาะ
*(2) เมื่อผู้ใช้ดูวิดีโอเสร็จแล้ว ฉันสามารถเข้าสู่ระบบรายการ (ใต้ข้อมูลผู้ใช้ใน DynamoDB) ว่าพวกเขาเคยดูวิดีโอใดแล้ว ตัวอย่างเช่น ตอนนี้อาจเป็นรายการที่เห็นแล้ว: [3,12,73,108,57] สำหรับวิดีโอ 5 รายการที่พวกเขาดูจนถึงตอนนี้ เมื่อผู้ใช้คลิก nextVideo() เราจะสร้าง newNumber แบบสุ่ม และเปรียบเทียบกับหมายเลขใดๆ ในรายการที่เห็นทันที ฉันใช้ seenlist.indexOf(newNumber)
และจะไปอีกครั้งหรือหยุดลงหากไม่มีหมายเลขใหม่อยู่ในรายการ จากนั้นฉันสามารถค้นหา GSI และดึงข้อมูลที่เกี่ยวข้องเพื่อแสดงวิดีโอจาก URLArray
ฉันคิดว่า indexOf()
นี้เป็นภาระในการคำนวณที่ใหญ่ที่สุดบนอุปกรณ์ และเห็นได้ชัดว่าจะช้าลงเล็กน้อยเมื่อ seenList
เพิ่มขึ้น แต่ควรจะเร็วกว่านี้ด้วยตัวเลขจำนวนเต็มล้วนๆ แล้วเป็นตัวอักษรและตัวเลข myKey
อย่างที่ฉันเคยใช้ ข้อเสนอแนะอื่นใดจะยินดี :)
ฉันยังไม่ได้ลอง แต่มันก็เป็นแค่ไอเดียเท่านั้น เพราะฉันต้องเก็บองค์ประกอบแบบสุ่มเอาไว้ แต่ก่อนอื่น คุณรู้ไหมว่าฉันสามารถค้นหาจำนวนแถวหรือจำนวนตารางของ URLArray ได้อย่างไร