【问题标题】:How can I subtract an array of values in a MongoDB query?如何在 MongoDB 查询中减去一组值?
【发布时间】:2016-07-17 01:48:32
【问题描述】:

我有一组文档,其中一个字段是 64 个数字的数组。我想构造一个返回这些文档的查询,其中这个数组已经被减去和求和,但是,我什至不知道如何做这个任务的减法部分。

示例文档可能如下所示。

{
"_id" : ObjectId("577be558033ad33f66684974"),
"syntactic_fingerprint" : [ 
    0.921382546424866, 
    0.048630952835083, 
    -0.251873761415482, 
    -0.0470362603664398, 
    0.0, 
    0.0296048410236835, 
    0.0319229736924171, 
    -0.0332595892250538, 
    -0.0694081708788872, 
    -0.117949850857258, 
    -0.0555221512913704, 
    -0.176394507288933, 
    0.0160530339926481, 
    -0.0234932824969292, 
    -0.0148191852495074, 
    0.0816841721534729, 
    0.0323052480816841, 
    0.0, 
    0.0, 
    0.0142431678250432, 
    0.0, 
    0.0, 
    0.0189650449901819, 
    0.0386682450771332, 
    0.0308650359511375, 
    0.0, 
    0.0310780759900808, 
    0.0361337624490261, 
    0.0, 
    0.0, 
    0.0, 
    0.0128832636401057, 
    -0.0125190699473023, 
    0.0, 
    -0.0282401368021965, 
    -0.0348126254975796, 
    -0.0154333971440792, 
    -0.0173368379473686, 
    -0.0443549081683159, 
    -0.0181444175541401, 
    -0.0224117543548346, 
    0.0, 
    -0.0689809918403625, 
    0.0, 
    -0.0300765186548233, 
    0.0, 
    0.0, 
    -0.0184972882270813, 
    0.0, 
    0.0, 
    0.0, 
    -0.0128712980076671, 
    0.0, 
    0.0, 
    0.0183296073228121, 
    -0.017868610098958, 
    0.0, 
    0.0, 
    -0.0145018044859171, 
    0.0134829748421907, 
    -0.0138665018603206, 
    0.0, 
    0.0, 
    0.0
]
}

我正在尝试构建一个查询,该查询将采用 64 个元素“syntactic_fingerprint”向量之一(作为常数),并从每个其他文档的指纹中减去它,然后将减去的指纹的值相加成一个号码。

这似乎应该通过聚合管道以某种方式实现......但我似乎无法找到一种优雅的方式来做到这一点。

【问题讨论】:

    标签: arrays mongodb subtraction


    【解决方案1】:

    您确实需要使用聚合管道来执行此操作。应该比较简单,你只需要$unwind数组,它会为数组中的每个元素创建一个文档,用于管道的下一个阶段。然后,您可以将其分组为一个结果,并累积文档中值的总和,并从每个元素中减去您的常数。

    示例(mongoshell js):

    db.myCollection.aggregate([
    {
      $match: {syntactic_fingerprint: myConstant}
    },
    {
      $unwind: '$syntactic_fingerprint'
    },
    {
      $group: {
        _id: null,
        sum: {$sum: {$subtract: ['$syntactic_fingerprint', myConstant]}}
      }
    }
    ]);
    

    _idnull 分组意味着它将累积到一个对象中。

    文档:

    【讨论】:

    • 感谢@tsturzl 的回答,但这不是我想做的。我想从每个元素中减去一个不同的值(由查询中的 64 元素数组指定),并返回仍然具有 64 元素数组的文档。 (从那里,我将总结所有内容,您提供的查询似乎很有帮助。)
    • 例如,在一个包含 4 个元素的更紧凑的情况下,假设一个文档有 fingerprint: [2, 4, 1, 2]。我可能想用数组[1, 4, 1, 1] 查询它并返回一个带有fingerprint: [1, 0, 0, 1] 的文档。 (从那里开始,我将所有内容相加得到2。)但是您明白为什么必须逐个元素地进行减法。
    • 不完全是,正如我试图在示例中展示的那样,常量将是一个数组,例如 [1, 0, 0, 1],其中从第一个值中减去 1,从第一个值中减去 0第二个值等。
    • @LoganWilliams 我不认为你想要完成的事情可以用聚合框架来完成,这更适合 MapReduce。
    【解决方案2】:

    如果算术运算是在两个选择文档之间计算的,则可能有一种方法可以聚合您需要的内容。但是,鉴于您提到您将查询数组 [1, 4, 1, 1],我认为如果没有一些 javascript/应用程序级别的查询,它是不可能的。我有一个粗略的方法,但它会返回一个数组而不是文档。

    //input would be from query, output would be the result, of course.
    var input = [1,4,1,1];
    var output = [];
    var count = 0;
    
    
    //unwind the fingerprints
    db.fingerprint.aggregate([
        {$unwind : "$fingerPrint" }
    ]).forEach(function(doc){
        id = doc._id.valueOf();
        output.push(doc.fingerPrint - input[count]);
        count++;
    })
    
    print(output);
    

    使用上面讨论的示例,结果将是[1, 0, 0 1]

    但是,如果您要使用两个文档进行算术运算,我也许可以使用查询来聚合它们。

    【讨论】:

    • 对两个文档进行算术运算也可能没问题——我现在唯一的用例是从一个文档的指纹中减去其他文档的指纹。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多