如果至少有一个元素匹配,如何聚合2个列表?

时间:2017-01-16 07:16:03

标签: mongodb

例如,我在集合中有6个项目

void set1KhzDC100()
{
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 500.000 kHz
// Mode: Fast PWM top=0x01FF
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x82;
TCCR1B=0x0A;
TCNT1H=0;
TCNT1L=0;
ICR1H=0x00;
ICR1L=0x00;
OCR1A=511;
}

void Set4KhzDC100()
{
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 4000.000 kHz
// Mode: Fast PWM top=0x03FF
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x83;
TCCR1B=0x09;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1A=1023;
OCR1BH=0x00;
OCR1BL=0x00;
}

void Set1KhzDC50()
{
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 500.000 kHz
// Mode: Fast PWM top=0x01FF
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x82;
TCCR1B=0x0A;
TCNT1H=0;
TCNT1L=0;
ICR1H=0x00;
ICR1L=0x00;
OCR1A=255;
}

我会进行查询以合并其列表中至少有1个元素匹配的所有项目。结果将是:

{ _id: 1, list: ["A", "B"] }
{ _id: 2, list: ["C", "A"] }
{ _id: 3, list: ["E", "F"] }
{ _id: 4, list: ["E", "D"] }
{ _id: 5, list: ["U", "I"] }
{ _id: 6, list: ["D", "K"] }

我是MongoDB的新手,所以有人帮我查询了这个问题吗?非常感谢。

1 个答案:

答案 0 :(得分:1)

我发现这个解决方案几乎解决了你的问题。

db.lists.aggregate([   
  {$unwind:"$list"},   
  {$group:{_id:"$list", merged:{$addToSet:"$_id"}, size:{$sum:1}}},
  {$match:{size: {$gt: 1}}},    
  {$project:{_id: 1, merged:1, size: 1, merged1: "$merged"}},    
  {$unwind:"$merged"},    
  {$unwind:"$merged1"},    
  {$group:{_id:"$merged", letter:{$first:"$_id"}, size:{$sum: 1}, set: {$addToSet:"$merged1"}}},    
  {$sort:{size:1}},    
  {$group:{_id: "$letter", mergedIds:{$last:"$set"}, size:{$sum:1}}},    
  {$match: {size:{$gt:1}}}
])

我在我的mongo shell中对此进行了测试,它提供了以下输出:

{ "_id" : "E", "matchedIds" : [ 6, 3, 4 ], "size" : 2 }
{ "_id" : "A", "matchedIds" : [ 1, 2 ], "size" : 2 }

matchedIds代表文档id - s,它们在list数组中具有共同价值。

我认为在上面的聚合中可以做一些优化,但最初我发现这个,会尝试寻找其他方法。此外,您可以在聚合pipline末尾使用$lookup聚合,以使id - s与set值匹配。我无法测试这个,因为我的mongo版本不支持$lookup。但是如果你使用Node.js或其他东西,你可以在一些for循环中手动获取这些值。

<强>被修改

此算法仅在每个列表的相交列表数量不超过3时才有效。

例如,这将起作用:

{ "_id" : 1, "list" : [ "A", "B" ] }
{ "_id" : 2, "list" : [ "C", "A" ] }
{ "_id" : 3, "list" : [ "E", "F" ] }
{ "_id" : 4, "list" : [ "E", "D" ] }
{ "_id" : 5, "list" : [ "U", "I" ] }
{ "_id" : 6, "list" : [ "D", "K" ] }
{ "_id" : 7, "list" : [ "A", "L" ] }

但这不会:

{ "_id" : 1, "list" : [ "A", "B" ] }
{ "_id" : 2, "list" : [ "C", "A" ] }
{ "_id" : 3, "list" : [ "E", "F" ] }
{ "_id" : 4, "list" : [ "E", "D" ] }
{ "_id" : 5, "list" : [ "U", "I" ] }
{ "_id" : 6, "list" : [ "D", "K" ] }
{ "_id" : 7, "list" : [ "L", "K" ] }

这里带有7,6,4,3的id的列表有交集,因此相交列表的数量是4,在这种情况下,提供的算法将不起作用。只有当每个列表的交叉量小于4时,它才会起作用

最终通知

通过在mongo数据库层中进行合并计算,您似乎无法实现所需的结果。如果您正在构建应用程序,那么在应用程序层中进行计算也会更好。