How to sort result by number of refs in MongoDB?

Viewed 21

I'm creating an inventory application, in which items can be added to an inventories. Items and inventories share a many-to-many relationship. These are my schemas for both:

const itemSchema = mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  emoji: {
    type: String,
    required: true,
  },
  createdBy: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
    default: null,
  },
  category: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category',
  },
});

const inventorySchema = mongoose.Schema({
  owner: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
  },
  access: {
    type: String,
    enum: ['PRIVATE', 'PUBLIC'],
    default: 'PRIVATE',
  },
  category: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category',
  },
  items: [
    {
      item: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Item',
      },
      quantity: {
        type: Number,
        default: 0,
      },
    },
  ],
  sharedWith: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Group',
    },
  ],
});

What I require...
I basically want to apply a sort to return me all the items in the order from most added to least added (in all Inventories).
I can create a counter field inside the Item Model and update it every time an item is added or removed from an inventory, but it does not seem like the solution for this. Any help would be appreciated!

1 Answers

You did not provide sample documents but is sounds like this should work:

  1. Keep only necessary fields
  2. $unwind so each item in each inventory is a document
  3. $group items by _id and count the quantity for each.
  4. Format the data and sort by count
db.inventories.aggregate([
  {$project: {items: 1, _id: 0}},
  {$unwind: "$items"},
  {$group: {_id: "$items.item", count: {$sum: "$items.quantity"}}},
  {$lookup: {
      from: "items",
      localField: "_id",
      foreignField: "_id",
      as: "item"
    }
  },
  {$project: {item: {$mergeObjects: [{$first: "$item"}, {count: "$count"}]}}},
  {$replaceRoot: {newRoot: "$item"}},
  {$sort: {count: -1}}
])
Related