ApostropheCMS游标使用问题:.find()未定义,求正确实现位置
.find() is undefined Error in ApostropheCMS People Pieces Cursors Hey there! Let's work through your cursor reuse issue in the People Pieces module step by step.
1. Correct Placement for Cursor Code
Cursors in ApostropheCMS are server-side tools, so they can't be used directly in frontend assets (like code loaded via self.pushAsset). Here are the valid, reliable places to implement your cursor logic:
Option A: Inside the People Pieces Module (people/index.js)
Use lifecycle hooks that run after the module is fully initialized. The afterInit hook is ideal here, as it ensures all piece types and managers are registered and ready to use:
module.exports = { extend: '@apostrophecms/piece', name: 'person', afterInit(self) { // Example: Register a custom API endpoint to fetch filtered people self.apos.app.get('/api/people/engineering-team', async (req, res) => { try { // Use the module's built-in find method (cleaner than getManager) const peopleCursor = self.find(req) .and({ department: 'Engineering' }) .sort({ lastName: 1 }) .limit(15); const engineeringTeam = await peopleCursor.toArray(); res.json(engineeringTeam); } catch (err) { res.status(500).json({ error: err.message }); } }); } };
Option B: Inside a People Widget (people-widget/index.js)
If you need cursor logic to populate a widget with dynamic data, use the load method (runs server-side before the widget is rendered to the frontend):
module.exports = { extend: '@apostrophecms/widget-type', name: 'people-widget', async load(self, req, widgets) { for (const widget of widgets) { // Fetch people matching the widget's configured filters widget.matchedPeople = await self.apos.docs.find(req, 'person') .and({ location: widget.selectedLocation }) .sort({ hireDate: -1 }) .toArray(); } } };
2. Requirements for Using apos.docs.getManager()
The .find() is undefined error almost always stems from one of these issues:
- Timing: You're calling
getManagertoo early (before Apostrophe finishes initializing all modules). Never call it at the top of yourconstructmethod—stick to hooks likeafterInit,load, or custom API routes. - Incorrect Piece Name: Double-check that your People module's
nameis set toperson(it must exactly match the string passed togetManager('person')). - Wrong Method Usage: The document manager returned by
getManagerdoesn't have a directfind()method. Instead, useself.apos.docs.find(req, 'person')to create a cursor for thepersonpiece type, or use the module's ownself.find(req)if you're working inside the People module itself.
3. Adapting Cursors to Your People Schema
Once you have a valid cursor, you can chain methods to filter, sort, and limit results based on your custom schema fields. For example, if your People schema includes jobTitle, department, and hireDate:
// Filter by department, sort by hire date (newest first), limit to 5 const recentHires = await self.find(req) .and({ department: 'Marketing' }) .sort({ hireDate: -1 }) .limit(5) .toArray(); // Fetch only published people with specific job titles const seniorStaff = await self.apos.docs.find(req, 'person') .and({ jobTitle: { $in: ['Senior Developer', 'Lead Designer'] }, published: true }) .toArray();
Remember: Always end your cursor chain with an execution method like toArray(), toObject(), or count() to run the query and retrieve results.
内容的提问来源于stack exchange,提问作者Amin Shazrin

