You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Mongoose中存储支持自定义排序的嵌套图书分类数据的最佳方案

Hey there! Let's walk through your options for building that library structure in Mongoose, since you’re focused on sortable categories and sortable books within each category. I’ll break down the pros and cons of each approach, plus how to handle your core sorting needs.

First, let’s recap your core requirements to keep us aligned:

  • Let users select book categories from a preset list
  • Support arbitrary sorting of categories
  • Support arbitrary sorting of books within each category

Option 1: Nested Object (Direct Category Keys)

This approach mirrors your original JSON structure almost exactly, using object keys for category names and arrays for books. Since MongoDB 3.6+, document key order is preserved, but we’ll add an extra array to handle dynamic category sorting.

Implementation Code

const BookSchema = new mongoose.Schema({
  id: { type: Number, required: true },
  title: { type: String, required: true },
  price: { type: Number, required: true }
});

const LibrarySchema = new mongoose.Schema({
  // Store categories as object keys, values are book arrays
  categories: {
    type: Object,
    default: {}
  },
  // Track category order for custom sorting
  categoryOrder: {
    type: [String],
    default: []
  }
});

const Library = mongoose.model('Library', LibrarySchema);

Pros & Cons

  • Pros:
    • Matches your initial JSON structure perfectly, so data is intuitive
    • Book array order is preserved by MongoDB, so sorting books within a category just requires reordering the array elements
  • Cons:
    • Dynamic category sorting (like user-driven drag-and-drop) isn’t possible with just object keys, hence the need for the categoryOrder array
    • Querying a single category’s books requires syntax like library.categories['Book category 1'], which is a bit clunky
    • Harder to maintain if you end up with a huge number of categories

Option 2: Map Type with Subschema

Mongoose’s Map type gives you a more structured way to handle dynamic category keys, with built-in methods like get() and set() for safer operations.

Implementation Code

const BookSchema = new mongoose.Schema({
  id: { type: Number, required: true },
  title: { type: String, required: true },
  price: { type: Number, required: true }
});

const LibrarySchema = new mongoose.Schema({
  // Map keys = category names, values = book arrays
  categories: {
    type: Map,
    of: [BookSchema],
    default: {}
  },
  // Still need a separate array to track custom category order
  categoryOrder: {
    type: [String],
    default: []
  }
});

const Library = mongoose.model('Library', LibrarySchema);

Pros & Cons

  • Pros:
    • Mongoose’s Map API is safer than directly manipulating object keys (avoids accidental overwrites)
    • Book array order is preserved just like the nested object approach
  • Cons:
    • Same as the nested object approach: you still need categoryOrder to handle custom category sorting
    • Some MongoDB queries (like filtering categories that contain a specific book) are less straightforward with Maps

If your top priority is flexible, easy-to-maintain sorting for both categories and books, storing categories as an array of objects is the best bet. This eliminates the need for a separate order array entirely.

Implementation Code

const BookSchema = new mongoose.Schema({
  id: { type: Number, required: true },
  title: { type: String, required: true },
  price: { type: Number, required: true }
});

const CategorySchema = new mongoose.Schema({
  name: { type: String, required: true, unique: true },
  books: { type: [BookSchema], default: [] }
});

const LibrarySchema = new mongoose.Schema({
  categories: { type: [CategorySchema], default: [] }
});

const Library = mongoose.model('Library', LibrarySchema);

Pros & Cons

  • Pros:
    • Category sorting is as simple as reordering elements in the categories array—no extra order tracking needed
    • Book sorting within a category works the same way (reorder the books array)
    • Querying and filtering categories is much easier (e.g., findOne({ 'categories.name': 'Book category 1' }))
    • Far more extensible: you can easily add extra fields to categories later (like descriptions or creation dates)
  • Cons:
    • The structure doesn’t match your original JSON exactly, but you can easily convert it to your desired format after querying (e.g., using Array.reduce() to turn the categories array into a keyed object)

How to Handle Sorting in Practice

No matter which approach you choose, here’s how to implement the sorting logic:

Category Sorting

  • For Object/Map approaches:
    Use the categoryOrder array to dictate the order when retrieving data:
    const library = await Library.findById(libraryId);
    // Generate sorted categories based on the order array
    const sortedCategories = library.categoryOrder.map(categoryName => ({
      name: categoryName,
      books: library.categories.get(categoryName) || [] // Use library.categories[categoryName] for objects
    }));
    
  • For Array approach:
    Simply reorder the categories array elements and save the document—MongoDB will preserve the new order.

Book Sorting Within a Category

Across all approaches, books are stored in arrays, so sorting just involves reordering array elements:

const library = await Library.findById(libraryId);
// Find the target category (example using array approach)
const targetCategory = library.categories.find(cat => cat.name === 'Book category 1');
// Find the index of the book to reorder
const bookIndex = targetCategory.books.findIndex(book => book.id === 2);
// Move the book to the first position
const [movedBook] = targetCategory.books.splice(bookIndex, 1);
targetCategory.books.unshift(movedBook);
// Save the updated library
await library.save();

Final Recommendation

  • If you need to stick closely to your original JSON structure, go with the nested object or Map approach—just don’t forget the categoryOrder array for dynamic sorting.
  • If flexibility and long-term maintainability are more important, the array of categories approach is the clear winner. It makes sorting trivial and leaves room for future feature additions.

内容的提问来源于stack exchange,提问作者david987

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 16:37:36