mongodb - mongodb - map 减少和查找

标签 mongodb sorting join mapreduce

是否可以在同一个查询管道中高效地同时执行 map reduce 和 lookup?

假设我有两个集合:

  • 项目:{ _id, group_id, createdAt }
  • 购买:{ _id, item_id }

我想根据每组最近 x 件商品的购买次数获得前 n 件商品组。

如果我在商品文档中有可用的购买数量,那么我可以聚合和排序,但事实并非如此。

我可以获得每组最近的 x 项:

let x = 3;
let map = function () {
  emit(this.group_id, { items: [this] });
};
let reduce = function (key, values) {
  return { items: getLastXItems(x, values.map(v => v.items[0])) };
};
let scope = { x };

db.items.mapReduce(map, reduce, { out: { inline: 1 }, scope }, function(err, res) {
  if (err) {
    ...
  } else {
    // res is an array of { group_id, items } where items is the last x items of the group
  }
});

但我缺少购买计数,所以我不能用它来对组进行排序,并输出前 n 个组(顺便说一句,我什至不确定我能做到这一点)

我在 Web 服务器上使用它,并根据用户上下文运行具有范围变量的查询,因此我不想将结果输出到另一个集合并且必须内联执行所有操作。

=== edit 1 === 添加数据示例:

示例数据可以是:

// items
{ _id: '1, group_id: 'a', createdAt: 0 }
{ _id: '2, group_id: 'a', createdAt: 2 }
{ _id: '3, group_id: 'a', createdAt: 4 }
{ _id: '4, group_id: 'b', createdAt: 1 }
{ _id: '5, group_id: 'b', createdAt: 3 }
{ _id: '6, group_id: 'b', createdAt: 5 }
{ _id: '7, group_id: 'b', createdAt: 7 }
{ _id: '8, group_id: 'c', createdAt: 5 }
{ _id: '9, group_id: 'd', createdAt: 5 }

// purchases
{ _id: '1', item_id: '1' }
{ _id: '2', item_id: '1' }
{ _id: '3', item_id: '3' }
{ _id: '4', item_id: '5' }
{ _id: '5', item_id: '5' }
{ _id: '6', item_id: '6' }
{ _id: '7', item_id: '7' }
{ _id: '8', item_id: '7' }
{ _id: '9', item_id: '7' }
{ _id: '10', item_id: '3' }
{ _id: '11', item_id: '9' }

n = 3x = 2 的示例结果将是:

[
  group_id: 'a', numberOfPurchasesOnLastXItems: 4,
  group_id: 'b', numberOfPurchasesOnLastXItems: 3,
  group_id: 'c', numberOfPurchasesOnLastXItems: 1,
]

最佳答案

我认为这可以通过聚合管道解决,但我不知道这有多糟糕,尤其是在性能方面。

我担心的是:

  • 聚合管道能否在查找和排序时从索引中获益?
  • 能不能简化一下只用来统计匹配项的lookup + projection

无论如何,我认为我可以采用的一种解决方案是:

x = 2;
n = 3;

items.aggregate([
  {
    $lookup: {
      from: 'purchases',
      localField: '_id',
      foreignField: 'item_id',
      as: 'purchases',
    },
  },
  /*
  after the join, the data is like {
    _id: <itemId>,
    group_id: <itemGroupId>,
    createdAt: <itemCreationDate>,
    purchases: <arrayOfPurchases>,
  }
  */

  {
    $project: {
      group_id: 1,
      createdAt: 1,
      pruchasesCount: { $size: '$purchases' },
    }
  }
  /*
  after the projection, the data is like {
    _id: <itemId>,
    group_id: <itemGroupId>,
    createdAt: <itemCreationDate>,
    purchasesCount: <numberOfPurchases>,
  }
  */

  {
    $sort: { createdAt: 1 }
  },

  {
    $group: {
      _id: '$group_id',
      items: {
        $push: '$purchasesCount',
      }
    }
  }
  /*
  after the group, the data is like {
    _id: <groupId>,
    items: <array of number of purchases per item, sorted per item creation date>,
  }
  */

  {
    $project: {
      numberOfPurchasesOnMostRecentItems: { $sum: { $slice: ['$purchasesCount', x] } },
    }
  }
  /*
  after the projection, the data is like {
    _id: <groupId>,
    numberOfPurchasesOnMostRecentItems: <number of purchases on the last x items>,
  }
  */

  {
    $sort: { numberOfPurchasesOnMostRecentItems: 1 }
  },

  { $limit : n }
]);

关于mongodb - mongodb - map 减少和查找,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39605686/

相关文章:

mongodb - Moped:运行裸 mongo 命令

R 表函数 : how to coerce order of column names output of table()

Python 按字母顺序对字符串进行排序,小写在前

mysql - 根据表 1 上的每个 id 连接 2 个表

mongodb - 将用户从 Firebase 迁移到 MongoDB

mongodb - $lookup 无法在 mongodb 中显示不相关的记录

arrays - 比较 MongoDB 中的数组

algorithm - 冒泡排序算法分析

php - 多个表多列连接到同一个表

java - 为什么 JPA join 返回太多结果?