Project Templates
Social Network
How to build a backend for a social network?
47 นาที
บทนำ ในคู่มือนี้ คุณจะได้ค้นพบวิธีการตั้งค่าระบบแบ็คเอนด์ที่แข็งแกร่งสำหรับเครือข่ายสังคมโดยใช้ แพลตฟอร์มแบ็คเอนด์เป็นบริการ ระบบแบ็คเอนด์นี้จะถูกออกแบบมาเพื่อจัดการการตรวจสอบสิทธิ์ผู้ใช้ การจัดการข้อมูล การสื่อสารแบบเรียลไทม์ และอื่นๆ—ทั้งหมดนี้ในขณะที่มั่นใจในความปลอดภัยและประสิทธิภาพ เมื่อสิ้นสุดการสอนนี้ โครงการของคุณจะมีลักษณะดังนี้ ภาพรวมเครือข่ายสังคม เคล็ดลับ สำหรับโค้ดต้นฉบับทั้งหมด โปรดเยี่ยมชมที่เก็บ github ของเราที่ github https //github com/templates back4app/back4gram ข้อคิดสำคัญ การจัดการ backend ที่เรียบง่าย ใช้ backend ที่จัดการโดย back4app เพื่อทำให้การตรวจสอบผู้ใช้ การจัดเก็บข้อมูล และฟังก์ชันการทำงานแบบเรียลไทม์เป็นไปอย่างราบรื่น การโต้ตอบแบบเรียลไทม์ ใช้ livequery เพื่อเปิดใช้งานการส่งข้อความแบบไดนามิกและการอัปเดตเนื้อหาในทันที การจัดการผู้ใช้และเนื้อหาที่ครอบคลุม สร้างระบบที่แข็งแกร่งสำหรับโปรไฟล์ผู้ใช้ โพสต์ ความคิดเห็น และการโต้ตอบทางสังคม ความสามารถในการขยายและประสิทธิภาพ ใช้การปรับแต่งการค้นหา การแคช และการดำเนินการแบบกลุ่มเพื่อรักษาประสิทธิภาพสูงเมื่อเครือข่ายของคุณเติบโต การรวมที่ทันสมัย ปรับปรุง backend ของคุณด้วย cloud functions งานเบื้องหลัง และการแจ้งเตือนแบบพุชเพื่อประสบการณ์ผู้ใช้ที่ดียิ่งขึ้น ข้อกำหนดเบื้องต้น ก่อนที่คุณจะเริ่ม ให้แน่ใจว่าคุณมี บัญชี back4app ลงทะเบียนฟรีที่ back4app com https //www back4app com/ node js และ npm ติดตั้ง node js (v14 x หรือใหม่กว่า) จาก nodejs org https //nodejs org/ ความรู้พื้นฐานเกี่ยวกับ javascript และ react โปรแกรมแก้ไขโค้ด ใช้โปรแกรมแก้ไขเช่น visual studio code หรือ sublime text ขั้นตอนที่ 1 — การกำหนดค่าของ backend back4app ของคุณ การสร้างโปรเจกต์ใหม่บน back4app ลงชื่อเข้าใช้แดชบอร์ด back4app ของคุณ คลิกที่ "สร้างแอปใหม่" ตั้งชื่อแอปของคุณ (เช่น "back4social") และเลือกภูมิภาคเซิร์ฟเวอร์ที่ใกล้ที่สุดกับคุณ เมื่อโปรเจกต์ถูกสร้างขึ้น คุณจะเห็นมันถูกแสดงในแดชบอร์ด back4app ของคุณ โปรเจกต์นี้จะเป็นพื้นฐานสำหรับการกำหนดค่าด้านหลังทั้งหมดที่กล่าวถึงในบทช่วยสอนนี้ การออกแบบสคีมาฐานข้อมูล แบ็กเอนด์ของเครือข่ายสังคมของคุณจะใช้คลาสต่อไปนี้ ผู้ใช้ (จัดเตรียมโดย parse โดยค่าเริ่มต้น) ขยายด้วยฟิลด์เช่นประวัติและรูปโปรไฟล์ โพสต์ เก็บเนื้อหาข้อความและการอัปโหลดภาพ ความคิดเห็น เก็บความคิดเห็นของผู้ใช้เกี่ยวกับโพสต์ การสนทนา แสดงถึงเซสชันแชทระหว่างผู้ใช้ ข้อความ ประกอบด้วยข้อความแต่ละข้อความในการสนทนา สถานะการพิมพ์ บ่งบอกเมื่อผู้ใช้กำลังพิมพ์ การเพิ่มคลาสฐานข้อมูล ใน back4app ข้อมูลจะถูกเก็บใน คลาส คุณสามารถสร้างคลาสใหม่ในแดชบอร์ด back4app หรือผ่านตัวแทน ai ในการสร้างโดยใช้แดชบอร์ดโปรด ไปที่ส่วน “ฐานข้อมูล” ในแดชบอร์ด back4app ของคุณ สร้างคลาสใหม่ และเพิ่มคอลัมน์ที่เกี่ยวข้อง เช่น ชื่อ (string) และ iscompleted (boolean) แบ็กเอนด์เครือข่ายสังคมของคุณจะใช้คลาสต่อไปนี้ ในการตั้งค่าฐานข้อมูลของคุณ ไปที่ "ฐานข้อมูล" ในแดชบอร์ด back4app ของคุณ ปรับปรุงคลาสผู้ใช้ เปิดคลาส user ที่มีอยู่ เพิ่มคอลัมน์ ชีวประวัติ (สตริง) อวตาร (ไฟล์) ผู้ติดตาม (จำนวน, ค่าเริ่มต้น 0) ตาม (หมายเลข, ค่าเริ่มต้น 0) สร้างคลาสโพสต์ คลิก "สร้างคลาส" ตั้งชื่อมัน โพสต์ และเพิ่ม เนื้อหา (สตริง) ผู้เขียน (ชี้ไปที่ ผู้ใช้ ) ภาพ (ไฟล์) ชอบ (จำนวน, ค่าเริ่มต้น 0) ชอบโดย (อาเรย์) สร้างคลาส comment ตั้งชื่อมัน ความคิดเห็น และรวมถึง เนื้อหา (สตริง) ผู้เขียน (ชี้ไปที่ ผู้ใช้ ) โพสต์ (ชี้ไปที่โพสต์) สร้างคลาสการสนทนา ตั้งชื่อมัน การสนทนา และเพิ่ม ผู้เข้าร่วม (อาเรย์) ข้อความสุดท้าย (สตริง) สร้างคลาสข้อความ ตั้งชื่อมัน ข้อความ และเพิ่ม ข้อความ (สตริง) ผู้ส่ง (ชี้ไปที่ ผู้ใช้ ) การสนทนา (ชี้ไปที่การสนทนา) สร้างคลาส typingstatus ตั้งชื่อมัน typingstatus และเพิ่ม ผู้ใช้ (ชี้ไปที่ ผู้ใช้ ) การสนทนา (ชี้ไปที่การสนทนา) กำลังพิมพ์ (บูลีน) ในการสร้างโดยใช้ ai agent กรุณา เปิด ai agent จากแดชบอร์ดแอปของคุณหรือเมนู อธิบายโมเดลข้อมูลของคุณ ด้วยภาษาที่เข้าใจง่าย ให้ ai agent สร้างสคีมา โดยอัตโนมัติ การกำหนดค่าการอนุญาตของคลาส เพื่อปกป้องข้อมูลของคุณ ปรับระดับการอนุญาตของคลาส (clps) ไปที่ "ความปลอดภัยและกุญแจ" ในแดชบอร์ดของคุณ ภายใต้ "ความปลอดภัยระดับคลาส" , ตั้งค่ากฎการอ่าน/เขียน ตัวอย่างเช่น อนุญาตให้เข้าถึงการอ่านสาธารณะสำหรับ โพสต์ ในขณะที่จำกัดการอัปเดต/ลบให้กับผู้เขียนโพสต์ การเปิดใช้งานฟีเจอร์เรียลไทม์ด้วย livequery ใน "การตั้งค่าเซิร์ฟเวอร์" , ค้นหา parse server และเปิดใช้งาน livequery รวมคลาสเหล่านี้สำหรับการตรวจสอบเรียลไทม์ ข้อความ สถานะการพิมพ์ โพสต์ (เพื่ออัปเดตไลค์และความคิดเห็นในเรียลไทม์) การตั้งค่า livequery ดึงคีย์แอปพลิเคชันของคุณ ไปที่ "การตั้งค่าแอป" > "ความปลอดภัย & คีย์" บันทึก application id , javascript key , server url , และ livequery server url คีย์ความปลอดภัย ขั้นตอนที่ 2 — เชื่อมโยง frontend ของคุณกับ back4app การตั้งค่าตัวแปรสภาพแวดล้อม สร้างไฟล์ env local ในไดเรกทอรีรากของโปรเจกต์ของคุณ react app parse app id=your application id react app parse js key=your javascript key react app parse server url=https //parseapi back4app com react app parse live query url=wss\ //your app id back4app io แทนที่ค่าตัวแปรด้วยข้อมูลรับรองจริงของคุณ การกำหนดค่าของ parse sdk สร้างไฟล์การกำหนดค่าเพื่อตั้งค่า parse // src/utils/parseconfig js import parse from 'parse/dist/parse min js'; // initialize parse with your environment variables parse initialize( process env react app parse app id, process env react app parse js key ); parse serverurl = process env react app parse server url; // enable livequery if configured if (process env react app parse live query url) { parse livequeryserverurl = process env react app parse live query url; } export default parse; จากนั้นนำเข้าไฟล์นี้ในจุดเริ่มต้นของแอปของคุณ (เช่น, index js ) // src/index js import react from 'react'; import reactdom from 'react dom/client'; import ' /index css'; import app from ' /app'; import ' /utils/parseconfig'; // initialize parse const root = reactdom createroot(document getelementbyid('root')); root render( \<react strictmode> \<app /> \</react strictmode> ); ขั้นตอนที่ 3 — การตั้งค่าการตรวจสอบสิทธิผู้ใช้ back4app’s parse server มีระบบการจัดการผู้ใช้ในตัวผ่าน parse user คลาส parse จัดการผู้ใช้ได้อย่างไร จัดการข้อมูลประจำตัวของผู้ใช้ (ชื่อผู้ใช้, อีเมล, รหัสผ่าน) จัดการสถานะการตรวจสอบสิทธิและโทเค็นเซสชัน ทำให้กระบวนการลงทะเบียนและเข้าสู่ระบบง่ายขึ้น ตัวอย่างการลงทะเบียนผู้ใช้ // function to handle user sign up const handlesignup = async () => { try { const user = new parse user(); user set('username', username); user set('email', email); user set('password', password); // set additional user info user set('bio', ''); user set('followers', 0); user set('following', 0); await user signup(); console log('registration successful'); navigate('/feed'); } catch (error) { console error('sign up error ', error message); // handle errors based on error codes if (error code === 202) { seterrors({ errors, username 'username is taken'}); } else if (error code === 203) { seterrors({ errors, email 'email already exists'}); } } }; ตัวอย่างการเข้าสู่ระบบผู้ใช้ // function to handle user login const handlelogin = async () => { try { const user = await parse user login(username, password); console log('login successful ', user getusername()); navigate('/feed'); } catch (error) { console error('login error ', error message); setloginerror(error message); } }; ตรวจสอบเซสชันที่มีอยู่ const checkcurrentuser = async () => { try { const currentuser = parse user current(); if (currentuser) { console log('logged in as ', currentuser getusername()); return currentuser; } return null; } catch (error) { console error('error checking user ', error); return null; } }; การดำเนินการรีเซ็ตรหัสผ่าน const handlepasswordreset = async () => { try { await parse user requestpasswordreset(email); console log('reset email sent'); setresetemailsent(true); } catch (error) { console error('password reset error ', error message); setreseterror(error message); } }; ขั้นตอนที่ 4 — การจัดการโพสต์ การสร้างโพสต์ใหม่ const createpost = async () => { if (!postcontent trim() && !postimage) { console error('please add content or an image'); return; } try { const post = parse object extend('post'); const newpost = new post(); newpost set('content', postcontent); newpost set('author', parse user current()); newpost set('likes', 0); newpost set('likedby', \[]); if (postimage) { const parsefile = new parse file(postimage name, postimage); await parsefile save(); newpost set('image', parsefile); } await newpost save(); console log('post created successfully'); return newpost; } catch (error) { console error('error creating post ', error message); throw error; } }; การดึงโพสต์ const fetchposts = async (page = 0, limit = 10) => { try { const post = parse object extend('post'); const query = new parse query(post); query include('author'); query descending('createdat'); query limit(limit); query skip(page limit); const results = await query find(); const posts = results map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, likedby post get('likedby') || \[], createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } })); return posts; } catch (error) { console error('error fetching posts ', error); throw error; } }; การใช้งานฟีเจอร์ถูกใจ/ไม่ถูกใจ const togglelike = async (postid) => { try { const currentuser = parse user current(); const userid = currentuser id; const post = parse object extend('post'); const query = new parse query(post); const post = await query get(postid); const likedby = post get('likedby') || \[]; const isliked = likedby includes(userid); if (isliked) { post set('likedby', likedby filter(id => id !== userid)); post set('likes', math max((post get('likes') || 1) 1, 0)); } else { post set('likedby', \[ likedby, userid]); post set('likes', (post get('likes') || 0) + 1); } await post save(); return !isliked; } catch (error) { console error('error toggling like ', error); throw error; } }; ขั้นตอนที่ 5 — เปิดใช้งานความคิดเห็นในโพสต์ การเพิ่มความคิดเห็น const addcomment = async (postid, commentcontent) => { if (!commentcontent trim()) { console error('comment cannot be empty'); return; } try { const post = parse object extend('post'); const postquery = new parse query(post); const post = await postquery get(postid); const comment = parse object extend('comment'); const comment = new comment(); comment set('content', commentcontent); comment set('author', parse user current()); comment set('post', post); await comment save(); console log('comment added successfully'); return comment; } catch (error) { console error('error adding comment ', error); throw error; } }; การดึงความคิดเห็นสำหรับโพสต์เฉพาะ const fetchcomments = async (postid) => { try { const post = parse object extend('post'); const postquery = new parse query(post); const post = await postquery get(postid); const comment = parse object extend('comment'); const query = new parse query(comment); query equalto('post', post); query include('author'); query ascending('createdat'); const results = await query find(); const comments = results map(comment => ({ id comment id, content comment get('content'), createdat comment get('createdat'), author { id comment get('author') id, username comment get('author') get('username'), avatar comment get('author') get('avatar') ? comment get('author') get('avatar') url() null } })); return comments; } catch (error) { console error('error fetching comments ', error); throw error; } }; ขั้นตอนที่ 6 — การจัดการโปรไฟล์ผู้ใช้ การดึงโปรไฟล์ผู้ใช้ const fetchuserprofile = async (userid) => { try { const query = new parse query(parse user); const user = await query get(userid); const post = parse object extend('post'); const postsquery = new parse query(post); postsquery equalto('author', user); postsquery include('author'); postsquery descending('createdat'); const posts = await postsquery find(); const userdata = { id user id, username user get('username'), bio user get('bio') || '', avatar user get('avatar') ? user get('avatar') url() null, followers user get('followers') || 0, following user get('following') || 0, posts posts map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, createdat post get('createdat') })) }; return userdata; } catch (error) { console error('error fetching user profile ', error); throw error; } }; การอัปเดตโปรไฟล์ผู้ใช้ const updateuserprofile = async (profiledata) => { try { const currentuser = parse user current(); if (profiledata bio !== undefined) { currentuser set('bio', profiledata bio); } if (profiledata avatarfile) { const parsefile = new parse file('avatar jpg', profiledata avatarfile); await parsefile save(); currentuser set('avatar', parsefile); } await currentuser save(); console log('profile updated successfully'); return currentuser; } catch (error) { console error('error updating profile ', error); throw error; } }; ขั้นตอนที่ 7 — การนำเสนอการส่งข้อความแบบเรียลไทม์ ฟีเจอร์ livequery ของ back4app ช่วยให้สามารถส่งข้อความแบบเรียลไทม์และแสดงตัวบ่งชี้การพิมพ์ได้ การสร้างการสนทนา const createconversation = async (participantids) => { try { const currentuser = parse user current(); const allparticipantids = \[ new set(\[currentuser id, participantids])]; const existingconversation = await findexistingconversation(allparticipantids); if (existingconversation) { return existingconversation; } const participantpointers = await promise all( allparticipantids map(async (id) => { const userquery = new parse query(parse user); return await userquery get(id); }) ); const conversation = parse object extend('conversation'); const conversation = new conversation(); conversation set('participants', participantpointers); conversation set('lastmessage', ''); await conversation save(); console log('conversation created successfully'); return conversation; } catch (error) { console error('error creating conversation ', error); throw error; } }; // helper to find an existing conversation (simplified for demo) const findexistingconversation = async (participantids) => { try { const conversation = parse object extend('conversation'); const query = new parse query(conversation); const results = await query find(); for (const conversation of results) { const participants = conversation get('participants') || \[]; const ids = participants map(p => p id); if (ids length === participantids length && ids every(id => participantids includes(id))) { return conversation; } } return null; } catch (error) { console error('error finding conversation ', error); return null; } }; การส่งข้อความ const sendmessage = async (conversationid, messagetext) => { try { const currentuser = parse user current(); const conversation = parse object extend('conversation'); const conversationquery = new parse query(conversation); const conversation = await conversationquery get(conversationid); const message = parse object extend('message'); const message = new message(); message set('text', messagetext); message set('sender', currentuser); message set('conversation', conversation); message set('read', false); await message save(); conversation set('lastmessage', messagetext); await conversation save(); console log('message sent successfully'); return message; } catch (error) { console error('error sending message ', error); throw error; } }; สมัครรับการอัปเดตข้อความผ่าน livequery const subscribetomessages = async (conversationid, onnewmessage) => { try { const message = parse object extend('message'); const query = new parse query(message); const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversationid; query equalto('conversation', conversationpointer); query include('sender'); const subscription = await query subscribe(); subscription on('create', (message) => { const newmessage = { id message id, text message get('text'), createdat message get('createdat'), sender { id message get('sender') id, username message get('sender') get('username'), avatar message get('sender') get('avatar') ? message get('sender') get('avatar') url() null }, read message get('read') }; onnewmessage(newmessage); if (message get('sender') id !== parse user current() id) { markmessageasread(message); } }); return subscription; } catch (error) { console error('error subscribing to messages ', error); throw error; } }; const markmessageasread = async (message) => { try { message set('read', true); await message save(); } catch (error) { console error('error marking message as read ', error); } }; การนำเสนอการพิมพ์ const updatetypingstatus = async (conversationid, istyping) => { try { const currentuser = parse user current(); const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversationid; const typingstatus = parse object extend('typingstatus'); const query = new parse query(typingstatus); query equalto('conversation', conversationpointer); query equalto('user', currentuser); let typingstatus = await query first(); if (typingstatus) { typingstatus set('istyping', istyping); } else { typingstatus = new typingstatus(); typingstatus set('conversation', conversationpointer); typingstatus set('user', currentuser); typingstatus set('istyping', istyping); } await typingstatus save(); } catch (error) { console error('error updating typing status ', error); } }; const subscribetotypingstatus = async (conversationid, ontypingstatuschange) => { try { const typingstatus = parse object extend('typingstatus'); const query = new parse query(typingstatus); const conversation = parse object extend('conversation'); const conversationpointer = new conversation(); conversationpointer id = conversationid; query equalto('conversation', conversationpointer); query include('user'); const subscription = await query subscribe(); subscription on('update', (typingstatus) => { const user = typingstatus get('user'); const istyping = typingstatus get('istyping'); ontypingstatuschange({ userid user id, username user get('username'), istyping }); }); subscription on('create', (typingstatus) => { const user = typingstatus get('user'); const istyping = typingstatus get('istyping'); ontypingstatuschange({ userid user id, username user get('username'), istyping }); }); return subscription; } catch (error) { console error('error subscribing to typing status ', error); throw error; } }; ขั้นตอนที่ 8 — การเพิ่มความสามารถในการค้นหา การค้นหาผู้ใช้ const searchusers = async (query, limit = 20) => { try { const userquery = new parse query(parse user); userquery matches('username', new regexp(query, 'i')); userquery limit(limit); const users = await userquery find(); const userresults = users map(user => ({ id user id, username user get('username'), avatar user get('avatar') ? user get('avatar') url() null, bio user get('bio') || '' })); return userresults; } catch (error) { console error('error searching users ', error); throw error; } }; การค้นหาบทความ const searchposts = async (query, limit = 20) => { try { const post = parse object extend('post'); const postquery = new parse query(post); postquery matches('content', new regexp(query, 'i')); postquery include('author'); postquery descending('createdat'); postquery limit(limit); const posts = await postquery find(); const postresults = posts map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } })); return postresults; } catch (error) { console error('error searching posts ', error); throw error; } }; การค้นหาแฮชแท็ก const searchhashtags = async (tag, limit = 20) => { try { const hashtagquery = tag startswith('#') ? tag substring(1) tag; const post = parse object extend('post'); const postquery = new parse query(post); postquery matches('content', new regexp(`#${hashtagquery}\\\b`, 'i')); postquery include('author'); postquery descending('createdat'); postquery limit(limit); const posts = await postquery find(); const hashtagresults = posts map(post => ({ id post id, content post get('content'), image post get('image') ? post get('image') url() null, likes post get('likes') || 0, createdat post get('createdat'), author { id post get('author') id, username post get('author') get('username'), avatar post get('author') get('avatar') ? post get('author') get('avatar') url() null } })); return hashtagresults; } catch (error) { console error('error searching hashtags ', error); throw error; } }; ขั้นตอนที่ 9 — การใช้ฟีเจอร์ขั้นสูงของ back4app back4app มีเครื่องมือขั้นสูง เช่น cloud functions, งานเบื้องหลัง และ hooks เพื่อเสริมสร้าง backend ของคุณ cloud functions สำหรับตรรกะฝั่งเซิร์ฟเวอร์ // cloud function example to notify users when a comment is added parse cloud aftersave("comment", async (request) => { if (request original) return; const comment = request object; const post = comment get("post"); const commenter = request user; const postquery = new parse query("post"); const fullpost = await postquery get(post id, { usemasterkey true }); const postauthor = fullpost get("author"); if (postauthor id === commenter id) return; const notification = parse object extend("notification"); const notification = new notification(); notification set("type", "comment"); notification set("fromuser", commenter); notification set("touser", postauthor); notification set("post", post); notification set("read", false); await notification save(null, { usemasterkey true }); }); การค้นหาขั้นสูงด้วย cloud code parse cloud define("advancedsearch", async (request) => { const { query, type, limit = 20 } = request params; if (!query) { throw new error("search query is required"); } let results = \[]; switch (type) { case 'users' const userquery = new parse query(parse user); userquery matches('username', new regexp(query, 'i')); userquery limit(limit); results = await userquery find({ usemasterkey true }); break; case 'posts' const post = parse object extend('post'); const postquery = new parse query(post); postquery matches('content', new regexp(query, 'i')); postquery include('author'); postquery limit(limit); results = await postquery find({ usemasterkey true }); break; default throw new error("invalid search type"); } return results; }); งานเบื้องหลังสำหรับงานที่เกิดซ้ำ parse cloud job("calculatetrendingtopics", async () => { const post = parse object extend("post"); const query = new parse query(post); const oneweekago = new date(); oneweekago setdate(oneweekago getdate() 7); query greaterthan('createdat', oneweekago); query limit(1000); const posts = await query find({ usemasterkey true }); const hashtagcounts = {}; posts foreach(post => { const content = post get('content') || ''; const hashtags = content match(/#(\w+)/g) || \[]; hashtags foreach(hashtag => { const tag = hashtag tolowercase(); hashtagcounts\[tag] = (hashtagcounts\[tag] || 0) + 1; }); }); const trendingarray = object entries(hashtagcounts) map((\[hashtag, count]) => ({ hashtag, count })) sort((a, b) => b count a count) slice(0, 10); const trendingtopics = parse object extend("trendingtopics"); const trending = new trendingtopics(); trending set("topics", trendingarray); trending set("calculatedat", new date()); await trending save(null, { usemasterkey true }); return "trending topics calculated successfully"; }); ฟีเจอร์ขั้นสูงเพิ่มเติม การแจ้งเตือนแบบพุช ใช้บริการพุชของ back4app เพื่อแจ้งเตือนผู้ใช้เกี่ยวกับข้อความใหม่ การควบคุมการเข้าถึงตามบทบาท กำหนดบทบาทเพื่อจัดการสิทธิ์สำหรับการกระทำต่างๆ เช่น การตรวจสอบเนื้อหา webhook รวมบริการภายนอกโดยการเรียกใช้งาน webhook จาก cloud code ขั้นตอนที่ 10 — การปรับแต่งประสิทธิภาพ เมื่อแบ็กเอนด์ของคุณขยายตัว การปรับแต่งประสิทธิภาพเป็นสิ่งสำคัญ พิจารณาเทคนิคต่อไปนี้ การสร้างดัชนีฐานข้อมูล สร้างดัชนีในฟิลด์ที่ถูกสอบถามบ่อย (เช่น ผู้เขียน , วันที่สร้าง , ชื่อผู้ใช้ ) เพื่อเพิ่มประสิทธิภาพการสอบถาม การปรับแต่งการสอบถาม ปรับแต่งการสอบถามโดยการเลือกเฉพาะฟิลด์ที่จำเป็นและใช้การแบ่งหน้าเพื่อลดชุดผลลัพธ์ การดำเนินการแบบกลุ่ม ใช้การอัปเดตและการลบแบบกลุ่มเพื่อลดการเรียก api const updatemultipleposts = async (postids, updatedata) => { try { const post = parse object extend('post'); const posts = postids map(id => { const post = new post(); post id = id; return post; }); posts foreach(post => { object entries(updatedata) foreach((\[key, value]) => { post set(key, value); }); }); await parse object saveall(posts); console log('posts updated successfully'); } catch (error) { console error('error updating posts ', error); throw error; } }; กลยุทธ์การแคช ใช้การแคชฝั่งไคลเอนต์สำหรับข้อมูลที่เข้าถึงบ่อยเพื่อลดการเรียก api การใช้ livequery อย่างมีประสิทธิภาพ สมัครสมาชิกเฉพาะข้อมูลที่จำเป็นและยกเลิกการสมัครเมื่อไม่ต้องการข้อมูลอีกต่อไป การเพิ่มประสิทธิภาพการจัดการไฟล์ ปรับขนาดภาพก่อนอัปโหลดเพื่อลดการใช้แบนด์วิธและพื้นที่จัดเก็บ const uploadresizedimage = async (originalfile, maxwidth = 1200, maxheight = 1200) => { return new promise((resolve, reject) => { try { const reader = new filereader(); reader onload = (event) => { const img = new image(); img onload = () => { let width = img width; let height = img height; if (width > maxwidth) { height = math round(height (maxwidth / width)); width = maxwidth; } if (height > maxheight) { width = math round(width (maxheight / height)); height = maxheight; } const canvas = document createelement('canvas'); canvas width = width; canvas height = height; const ctx = canvas getcontext('2d'); ctx drawimage(img, 0, 0, width, height); canvas toblob(async (blob) => { const resizedfile = new file(\[blob], originalfile name, { type originalfile type, lastmodified date now() }); const parsefile = new parse file(resizedfile name, resizedfile); await parsefile save(); resolve(parsefile); }, originalfile type, 0 8); }; img src = event target result; }; reader readasdataurl(originalfile); } catch (error) { reject(error); } }); }; การตรวจสอบและการขยาย ใช้การวิเคราะห์และบันทึกจากแดชบอร์ดของ back4app เพื่อตรวจสอบการใช้งาน api และประสิทธิภาพ พิจารณาการอัปเกรดแผนของคุณหรือใช้การแบ่งชิ้นส่วนและโซลูชัน cdn เมื่อฐานผู้ใช้ของคุณเติบโต บทสรุป ในบทแนะนำนี้ คุณได้เรียนรู้วิธีการตั้งค่าพื้นหลังของเครือข่ายสังคมด้วย back4app ซึ่งครอบคลุมการตรวจสอบผู้ใช้ การจัดการโพสต์ การส่งข้อความแบบเรียลไทม์ ฟีเจอร์การค้นหา และเทคนิคการปรับแต่งขั้นสูง โปรดอ่านบล็อกโพสต์ของเราที่อธิบาย วิธีการพัฒนาแอปโซเชียลมีเดีย ขอให้สนุกกับการเขียนโค้ดและโชคดีในพื้นหลังของเครือข่ายสังคมของคุณ!