在动态添加字段上排序

时间:2019-02-11 11:55:18

标签: javascript node.js mongodb sorting aggregation-framework

我通过以下方式在数据库中拥有2000万个文档。

 {
    "_id": ObjectId("5bb84e931cb3d25a3b21d14e"),
    "merchant": "menswearhouse.com",
    "category": "Fashion > Clothing > Men's Clothing",
    "feature": [
      "-0.899652959529",
      "-0.02401520125567913",
      "0.08394625037908554",
      "0.06319021433591843",
      "-0.015963224694132805"
    ]
  }

现在我有下面的数组,我需要用它来查找文档。

const dummy = [
  "-0.899652959529",
  "-0.02401520125567913",
  "0.08394625037908554",
  "0.06319021433591843",
  "-0.015963224694132805"
];

我需要

  1. 查找所有值的差,即需要用我的虚拟数组的第一个索引减去feature的第一个索引,以此类推,对于所有5个值,依此类推。
  2. 取所有值的平方
  3. 添加所有5个值
  4. 取平方根。
  5. 对该字段中的所有值进行排序,仅获得5个文档。

我正在使用此查询,当我使用$project$limit是该字段。但是我需要$sort字段为$project,并且需要阅读前5个文档。但是有两千万文档没有返回任何内容,并且永远存在。

db.collection.aggregate([
  { $project: {
    field: {
      $sqrt: {
        $sum: {
          $map: {
            input: { $range: [0, { $size: '$feature' }] },
            as: "d",
            in: {
              $pow: [
                {
                  $subtract: [
                    { $toDouble: { $arrayElemAt: [dummy, "$$d"] }},
                    { $toDouble: { $arrayElemAt: ["$feature", "$$d"] }}
                  ]
                },
                2
              ]
            }
          }
        }
      }
    }
  }}
])

我可以在运行时创建的字段上使用索引吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

简短的回答是“否”。您不能在运行时创建的字段上创建索引。在撰写本文时,MongoDB无法实现您想要的。但是您可以并行计算它们。假设服务器具有适当的资源(CPU和内存),则可以在应用程序中划分作业并并行执行。对于简单的数学,我们假设您有20,000,000(mil)个文档,并将它们分为20个任务。对于每个任务,它将处理1,000,000个文档并返回前5个结果。第一个任务的管道将是

[
    {
        '$sort': {
            '_id': 1
        }
    }, {
        '$skip': 0
    }, {
        '$limit': 1000000
    }, {
        '$project': {
            'field': {
                '$sqrt': {
                    <do your thing>
                }
            }
        }
    }, {
        '$limit': 5
    }
]

返回所有线程(任务)后,将结果(仅100个文档)合并到您的应用程序中,并按field进行排序,最后得到前5个文档。请注意,您必须考虑硬件资源以达到最佳数量的分割任务。