比较两个MongoDB集合之间的文档
我有两个现有集合,需要根据两个现有集合之间的比较填充第三个集合 需要比较的两个集合具有以下架构:比较两个MongoDB集合之间的文档,mongodb,join,Mongodb,Join,我有两个现有集合,需要根据两个现有集合之间的比较填充第三个集合 需要比较的两个集合具有以下架构: // Settings collection: { "Identifier":"ABC123", "C":"1", "U":"V", "Low":116, "High":124, "ImportLogId":1 } // Data collection { "Identifier":"ABC123", "C":"1", "U":"V", "Date":"11
// Settings collection:
{
"Identifier":"ABC123",
"C":"1",
"U":"V",
"Low":116,
"High":124,
"ImportLogId":1
}
// Data collection
{
"Identifier":"ABC123",
"C":"1",
"U":"V",
"Date":"11/6/2013 12AM",
"Value":128,
"ImportLogId": 1
}
一般来说,我对MongoDB和NoSQL都是新手,所以我很难掌握如何做到这一点。SQL将如下所示:
SELECT s.Identifier, r.ReadValue, r.U, r.C, r.Date
FROM Settings s
JOIN Reads r
ON s.Identifier = r.Identifier
AND s.C = r.C
AND s.U = r.U
WHERE (r.Value <= s.Low OR r.Value >= s.High)
db.settings.find().forEach(
function(doc) {
data = db.data.find({
Identifier: doc.Idendtifier,
C: doc.C,
U: doc.U,
$or: [{Value: {$lte: doc.Low}}, {Value: {$gte: doc.High}}]
}).toArray();
// Do what you need
}
)
{
"_id" : ObjectId("527a7f4b07c17a1f8ad009d2"),
"Identifier" : "ABC123",
"C" : "1",
"U" : "V",
"Low" : 116,
"High" : 124,
"ImportLogId" : 1,
"Data" : [
{
"Date" : ISODate("2013-11-06T00:00:00Z"),
"Value" : 128
},
{
"Date" : ISODate("2013-10-09T00:00:00Z"),
"Value" : 99
}
]
}
选择s.标识符、r.ReadValue、r.U、r.C、r.Date
从设置
连接读码器
在s.Identifier=r.Identifier上
和s.C=r.C
s.U=r.U
式中(r.值=s.高)
在本例中,使用示例数据,我希望返回一条记录,因为数据集合的值大于设置集合的高值。是否可以使用Mongo查询或map reduce实现这一点,或者这是一个糟糕的集合结构(即,可能所有这些都应该在一个集合中)
还有一些补充说明:
设置集合实际上每个“标识符”应该只有一条记录。每个“标识符”的数据收集将有许多记录。此过程可能一次扫描数十万个文档,因此资源考虑有点重要如果没有连接的概念,您必须更改方法并取消规范化
在您的情况下,看起来您正在进行数据日志验证。我的建议是循环设置收集,每个设置都使用操作符,以便在匹配的数据收集记录上设置验证标志;之后,您可以在数据采集上使用find操作符,通过新标志进行过滤。使用MongoDB执行类似操作没有好方法。如果您想要糟糕的方式,您可以使用如下代码:
SELECT s.Identifier, r.ReadValue, r.U, r.C, r.Date
FROM Settings s
JOIN Reads r
ON s.Identifier = r.Identifier
AND s.C = r.C
AND s.U = r.U
WHERE (r.Value <= s.Low OR r.Value >= s.High)
db.settings.find().forEach(
function(doc) {
data = db.data.find({
Identifier: doc.Idendtifier,
C: doc.C,
U: doc.U,
$or: [{Value: {$lte: doc.Low}}, {Value: {$gte: doc.High}}]
}).toArray();
// Do what you need
}
)
{
"_id" : ObjectId("527a7f4b07c17a1f8ad009d2"),
"Identifier" : "ABC123",
"C" : "1",
"U" : "V",
"Low" : 116,
"High" : 124,
"ImportLogId" : 1,
"Data" : [
{
"Date" : ISODate("2013-11-06T00:00:00Z"),
"Value" : 128
},
{
"Date" : ISODate("2013-10-09T00:00:00Z"),
"Value" : 99
}
]
}
但不要期望它的性能甚至远比任何像样的RDBMS好
您可以重建架构并从数据收集中嵌入文档,如下所示:
SELECT s.Identifier, r.ReadValue, r.U, r.C, r.Date
FROM Settings s
JOIN Reads r
ON s.Identifier = r.Identifier
AND s.C = r.C
AND s.U = r.U
WHERE (r.Value <= s.Low OR r.Value >= s.High)
db.settings.find().forEach(
function(doc) {
data = db.data.find({
Identifier: doc.Idendtifier,
C: doc.C,
U: doc.U,
$or: [{Value: {$lte: doc.Low}}, {Value: {$gte: doc.High}}]
}).toArray();
// Do what you need
}
)
{
"_id" : ObjectId("527a7f4b07c17a1f8ad009d2"),
"Identifier" : "ABC123",
"C" : "1",
"U" : "V",
"Low" : 116,
"High" : 124,
"ImportLogId" : 1,
"Data" : [
{
"Date" : ISODate("2013-11-06T00:00:00Z"),
"Value" : 128
},
{
"Date" : ISODate("2013-10-09T00:00:00Z"),
"Value" : 99
}
]
}
如果嵌入文档的数量较少,它可能会起作用,但老实说,使用文档数组远不是一种愉快的体验。更不用说,随着数据数组大小的增加,您可以轻松地达到文档大小限制
如果这种操作对于您的应用程序来说是典型的,我会考虑使用不同的解决方案。尽管我很喜欢MongoDB,但它只适用于特定类型的数据和访问模式 我们开发的一个功能名为,可能在这里有所帮助 它允许您比较两个MongoDB集合并查看差异(例如,找出相同、缺失或不同的字段) 然后,您可以将这些比较结果导出到CSV文件,并使用该文件创建新的第三个集合
披露:我们是MongoDB GUI Studio 3T的创建者 从
Mongo 4.4
开始,我们可以通过新的聚合阶段和经典的$group
阶段来实现这种类型的“连接”:
// > db.settings.find()
// { "Identifier" : "ABC123", "C" : "1", "U" : "V", "Low" : 116 }
// { "Identifier" : "DEF456", "C" : "1", "U" : "W", "Low" : 416 }
// { "Identifier" : "GHI789", "C" : "1", "U" : "W", "Low" : 142 }
// > db.data.find()
// { "Identifier" : "ABC123", "C" : "1", "U" : "V", "Value" : 14 }
// { "Identifier" : "GHI789", "C" : "1", "U" : "W", "Value" : 43 }
// { "Identifier" : "ABC123", "C" : "1", "U" : "V", "Value" : 45 }
// { "Identifier" : "DEF456", "C" : "1", "U" : "W", "Value" : 8 }
db.data.aggregate([
{ $unionWith: "settings" },
{ $group: {
_id: { Identifier: "$Identifier", C: "$C", U: "$U" },
Values: { $push: "$Value" },
Low: { $mergeObjects: { v: "$Low" } }
}},
{ $match: { "Low.v": { $lt: 150 } } },
{ $out: "result-collection" }
])
// > db.result-collection.find()
// { _id: { Identifier: "ABC123", C: "1", U: "V" }, Values: [14, 45], Low: { v: 116 } }
// { _id: { Identifier: "GHI789", C: "1", U: "W" }, Values: [43], Low: { v: 142 } }
这:
- 首先,通过新阶段将两个集合合并到管道中
- 继续进行
阶段,该阶段:$group
- 根据
、Identifier
和C
对记录进行分组U
- 将
s累积到数组中值
- 通过操作累积
s,以获得一个非Low
的null
值。使用Low
将不起作用,因为这可能会先使用$first
(对于数据集合中的元素)。而null
在合并包含非空值的对象时会丢弃$mergeObjects
值null
- 根据
- 然后丢弃
值大于150的合并记录Low
- 最后通过stage将结果记录输出到第三个集合