gpt4 book ai didi

javascript - 通过获取最新文档来减少mongodb的输出

转载 作者:行者123 更新时间:2023-11-28 19:47:11 24 4
gpt4 key购买 nike

好,这是我的收藏



{

"company" : "500010"

"eqtcorp" : {

"306113" : {
"DATE" : "2014-05-05 16:43:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "16:43"
},
"306118" : {
"DATE" : "2014-05-08 16:43:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "18:43"
},
"306114" : {
"DATE" : "2014-06-02 16:43:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "20:43"
}
"306116" : {
"DATE" : "2014-03-02 12:30:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "20:43"
}
"306115" : {
"DATE" : "2014-08-02 04:45:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "20:43"
}
"306117" : {
"DATE" : "2014-07-02 10:16:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "20:43"
}

.
.
.
.
.
}

}


如果我查询像

db.collection_name.find({"company": "500010"})


我会得到全部。由于“ eqtcorp”下有许多子文档,因此我只需要3个最新日期的子文档。只需在“ eqtcorp”下每个子文档中的“ DATE”字段的基础上进行反向排序,并获取前3个。这确实是一个挑战,因为我是Mongodb和mapreduce的新手。

我期望的输出是

{

"company" : "500010"

"eqtcorp" : {

"306113" : {
"DATE" : "2014-05-05 16:43:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "16:43"
},
"306118" : {
"DATE" : "2014-05-08 16:43:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "18:43"
},

"306116" : {
"DATE" : "2014-03-02 12:30:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "20:43"
}

}
}


有拍摄吗?

最佳答案

在这里,有几件事没有真正帮助您,实际上使原本简单的操作变得复杂。

您拥有的日期实际上是字符串,您应该将其更改为正确的BSON日期类型。它将在以后可能需要的地方为您提供帮助,因此应更改它们。幸运的是,它们至少在词法上受“ YYYY-MM-DD”的作用域限制,因此可以进行排序,但是不要期望它们有太多其他用途。

您实际上还应该使用数组,而不是通过键嵌套子文档。这些确实很难查询,因为您需要指定元素的确切路径。因此,您几乎总是受限于JavaScript处理,这比其他方法要慢得多。我会在稍后介绍,但继续:

您可以使用mapReduce进行以下操作:



db.collection.mapReduce(
function () {
for ( var k in this.eqtcorp ) {
this.eqtcorp[k].key = k;
emit( 1, this.eqtcorp[k] );
}
},
function (key,values) {

var reduced = {};

values.sort(function(a,b) {
return (( a.DATE > b.DATE ) ? -1 : (( a.DATE < b.DATE ) ? 1 : 0));
}).slice(-3).forEach(function(doc) {
reduced[doc.key] = doc;
});

return reduced;

},
{
"query": { "company": "50010" },
"finalize": function(key,vaue) {
for (var k in value) {
delete value[k].key;
}
return value;
},
"out": { "inline": 1 },
})
)


在映射器中,我当前正在使用发射的键作为 1。这样做的原因是,该语句将可以“聚合”多个文档中的所有结果。但是,如果您确实只想按照“公司”值执行此操作,则可以将其作为键发出,如:

            emit( this.company, this.eqtcorp[k] );


本质上,映射器将每个文档分解为仅输出“ eqtcorp”的每个子键作为其自己的文档。然后将这些传递给减速器。

可以多次调用的reducer将其作为“值”的输入数组作为同一个“键”,并使用该数组上的 sort首先对其进行处理。排序后(升序),然后 slice数组中的最后三项,并将每一项添加到简化结果中。

就像我说的那样,reducer可以被调用多次,所以每次通过不一定都获得每个分组键的“全部”值列表。这是“减少”阶段的基本部分,因为它“递增地”获取每个输入集并返回,最终运行已减少的结果的组合,直到只有一个“关键”值仅包含您所得到的三个结果为止想。

然后只有finalize函数可以清理一些便利整理工作,这些整理工作是通过原始的子文档密钥简化了结果处理的。其他事情仅仅是选择查询和输出选择,这取决于您的需求可能是另一个集合。或者,当然也可以省略选择查询来处理所有文档。



如前所述,文档结构无济于事,更适合于数组。因此,您应该拥有一个像这样的文档:

{

"company" : "500010",

"eqtcorp" : [

{
"key": "306113"
"DATE" : "2014-05-05 16:43:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "16:43"
},
{
"key": "306118",
"DATE" : "2014-05-08 16:43:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "18:43"
},
{
"key": "306114",
"DATE" : "2014-06-02 16:43:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "20:43"
},
{
"key:"306116",
"DATE" : "2014-03-02 12:30:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "20:43"
},
{
"key": "306115",
"DATE" : "2014-08-02 04:45:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "20:43"
},
{
"key": "306117",
"DATE" : "2014-07-02 10:16:00.000",
"subsection_name" : "CORPORATE NEWS",
"time" : "20:43"
}
]
}


尽管暂时不使用日期格式,但是这可以使事情变得更加整洁,因为您打算在整个集合中“查找最重要的三个值”,因此您可以简化处理过程,甚至可以使用聚合框架之类的方法来加快处理速度。这很简单:

db.collection.aggregate([

// Unwind the array
{ "$unwind": "$eqtcorp" },

// Sort the results by the dates
{ "$sort": "eqtcorp.DATE" -1 },

// Limit the top three results
{ "$limit": 3 },

// Optionally group back as an array
{ "$group": {
"_id": null,
"eqtcorp": { "$push": "$eqtcorp" }
}}

])


那将是整个系列的结果,并非不可能获得每个公司价值的前三名,而是要更多地参与其中,因为没有比分

db.collection.aggregate([

// Unwind the array
{ "$unwind": "$eqtcorp" },

// Sort the results by company and date
{ "$sort": "company": 1, "eqtcorp.DATE" -1 },

// Group back keeping the top value
{ "$group": {
"_id": "$company",
"all": { "$push": "$eqtcorp" },
"one": { "$first": "$eqtcorp" }
}},

// Unwind again
{ "$unwind": "$all" },

// match the "seen" value
{ "$project": {
"all": 1,
"one": 1,
"seen": {
"$eq": [ "$all", "$one" ]
}
}},

// Filter out "seen"
{ "$match": { "seen": false } },

// Group back keeping the new top
{ "$group": {
"_id": "$_id",
"all": { "$push": "$all },
"one": { "$first": "$one" },
"two": { "$first": "$all }
}},

// Unwind again
{ "$unwind": "$all" },

// Match the seen value
{ "$project": {
"all": 1,
"one": 1,
"two": 1,
"seen": {
"$eq": [ "$all", "$two" ]
}
}},

// Filter the seen value
{ "$match": { "seen": false } },

// Group back again
{ "$group": {
"_id": "$_id",
"one": { "$first": "$one" },
"two": { "$first": "$two },
"three": { "$first": "$three" }
}}
])


或在映射器处修改上面的map reduce,因为我们实际上只是人为地生成数组:

    function () {
this.eqtcorp.forEach(doc) {
emit( this.company, doc );
});
}


组合键时将其拆分仍然有意义



当然,如果文档之间没有进行实际的汇总,并且您的基本意图是仅获取每个文档中数组的最后三个值,那么明确的方法是在文档更新和项目添加时对它们进行“排序”数组。因此,您添加新项目的方法变为:

db.collection.update(
{ _id: document_id },
{
"$push": {
"eqtcorp": {
"$each": [ { new document }, { optionally more} ],
"$sort": { "DATE": 1 }
}
}
}
);


在MongoDB 2.6之前,这还需要一个 $slice修饰符,该修饰符基本上会对数组中的项目数施加上限,但不再需要。对于较早的版本,您可能必须为此提供一个上限值,例如 500或比预期结果大的其他数字,除非您实际上想“修剪”结果,在这种情况下要设置您的限制。

这里的要点是,不进行任何聚合,那么当您只想从文档中获取该数组的最后三个值时,就可以使用投影和在那里可用的 $slice运算符来完成此操作:

db.collection.find({},{ "eqtcorp": { "$slice": -3 } })


由于文档中的数组项已经排序,因此只需获取最后三个值即可。



因此,实际上,虽然可以使用mapReduce处理现有文档,但是除非您真的想汇总结果,否则它的过程要慢得多。通过快速,非常简单的查询,将数据更改为数组并保持排序顺序将立即获得所需的结果。

即使您的意图是聚合,使用数组时您可以使用的选项也要宽得多,并且通常更容易完成更复杂的事情。

关于javascript - 通过获取最新文档来减少mongodb的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24083512/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com