【问题标题】:MongoDB, Node and Express return all collections that don't exist in a separate collection that has a large amount of dataMongoDB、Node 和 Express 返回所有不存在于具有大量数据的单独集合中的集合
【发布时间】:2019-11-19 05:53:19
【问题描述】:

为了这个,我已经把头发拔了好几个星期了。

我有一个收藏(这是精简版):

const SubscriberSchema = new Schema({
  publication: { type: Schema.Types.ObjectId, ref: "publicationcollection" },
  buyer: { type: Schema.Types.ObjectId, ref: "buyercollection" },
  postCode: { type: String },
  modifiedBy: { type: String },
  modified: { type: Date }
});

我还有一个包含 175 万个英国邮政编码的集合

const PostcodeSchema = new Schema({
  postcode: { type: String }
});

我想要做的是返回订阅者集合中不存在于 Postcode 集合中的任何记录。

当我尝试使用 Mongoose 对订阅者集合中任何 >100 条记录进行非常简单的聚合时,我遇到超时或 >16MB 返回错误。

这是我迄今为止尝试过的:

router.get(
  "/badpostcodes/:id",
  passport.authenticate("jwt", { session: false }),
  (req, res) => {
    const errors = {};
    Subscriber.aggregate([
      {
        $match: {
          publication: mongoose.Types.ObjectId(req.params.id),
          postCode: { "$ne": null, $exists: true }
        }
      },
      {
        $lookup: {
          'from': 'postcodescollections',
          'localField': 'postCode',
          'foreignField': 'postcode',
          'as': 'founditem'
        }
      },
      // {
      //   $unwind: '$founditem'
      // },
      {
        $match: {
          'founditem': { $eq: [] }
        }
      }
    ], function (err, result) {
      if (err) {
        console.log(err);
      } else {
        if (result.length > 0) {
          res.json(result);
        } else {
          res.json("0");
        }
      }
    })
  }
);

unwind 似乎没有做任何事情,但它被注释掉以表明我尝试使用它。

我也尝试过在查找上使用管道,但没有奏效,类似于以下内容(抱歉,我没有尝试原始代码,所以这仅来自内存):

        $lookup: {
          'from': 'postcodescollections',
          'let': { 'postcode': "$postCode" },
          'pipeline': [
            {
              '$match': {
                'postcode': { $exists: false }
              }
            },
            {
              '$unwind': "$postCode"
            }
          ],
          'as': 'founditem'
        }

提前谢谢,希望我能留住一些头发!

【问题讨论】:

    标签: node.js mongodb express mongoose


    【解决方案1】:

    您正在对所有不匹配的邮政编码进行匹配,然后展开这些 - 这将是每个订阅者的 175 万份文档!我认为$lookup 中的语法也不正确。

    我认为您可以尝试以下方法 - 针对您的数据进行相应调整:

    执行$lookup 以在邮政编码中查找匹配的邮政编码,然后执行匹配以过滤那些没有任何founditem 元素的订阅者:"founditem.0": {$exists: false}

    看一个例子:

    db.getCollection("subscribers").aggregate(
        [
            // Stage 1
            {
                $match: {
                    postCode: { "$ne": null, $exists: true }
                }
            },
    
            // Stage 2
            {
                $project: { 
                    _id: 1,
                    postCode: 1
                }
            },
    
            // Stage 3
            {
                $lookup: {
                          from: "postcodescollections",
                          let: { p: "$postCode" },
                          pipeline: [
                            {
                              $match: {
                                  $expr:
                                    {
                                        $eq: ["$$p","$postcode"] }
                                  }
    
                            },
                            { $project: { _id: 1 } }
                          ],
                          as: "founditem"
                        }
            },
    
            // Stage 4
            {
                $match: {
                    "founditem.0": {$exists: false}
                }
            },
    
        ]
    );
    

    【讨论】:

    • 谢谢!好的,我已经尝试了很多版本,不幸的是它没有奏效。您原来的 $$p 导致超时。如果我删除了一个 $ 它会为每条记录返回空白的founditems
    • @fendify 没有问题。我已经测试了上述内容,$$ 的用法是按照docs 访问let 阶段中​​定义的变量。你是说答案没有用?
    • 不幸的是,它没有,不。您能否按照我的原始模型进行编辑,以防我编码不正确?订阅者模型中的“邮政编码”和邮政编码集合模型中的“邮政编码”?我已经尝试了多个版本,并且完全同意我应该返回匹配项,然后过滤不匹配项。
    • 您针对多少订户记录运行此操作?如果我尝试使用最少的文档(13000 个订阅者记录,并且每次都超时。除了主 ObjectID 之外,我是否需要向表中添加更多索引?这真的很令人沮丧,因为我可以使用 T-SQL 连接轻松地进行此查询,该连接可在几秒钟内返回结果!我很欣赏这可能只是我对基于文档的数据库缺乏了解,但我选择了 Mongo,因为它在我所做的任何其他查询上都优于 SQL。..
    • 我刚刚加载了 200 万个邮政编码集合,15000 个订阅者,留下了 1000 个没有匹配邮政编码的订阅者。在邮政编码上创建的索引。在我的机器上 2.4 秒内返回。您需要管道阶段中的索引和相关预测,并且应该能够解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-21
    • 1970-01-01
    • 2018-10-03
    相关资源
    最近更新 更多