$group mongodb 后获取常用元素

Posted

技术标签:

【中文标题】$group mongodb 后获取常用元素【英文标题】:Get common elements after $group mongodb 【发布时间】:2019-11-29 15:49:25 【问题描述】:

我有一些交易数据如下:

[
  "_id" : ObjectId("5d319aa8df4026532fe5036f"),
  "transaction" : ISODate("2018-10-16T04:00:07.000Z"),
  "cardnumber" : "1000 0000 0002 0356"
,
 "_id" : ObjectId("5d319aa8df4026532fe5035x"),
  "transaction" : ISODate("2018-10-16T04:00:07.000Z"),
  "cardnumber" : "1000 0000 0002 0358"
,
 "_id" : ObjectId("5d319aa8df4026532fe5036d"),
  "transaction" : ISODate("2018-09-16T04:00:07.000Z"),
  "cardnumber" : "1000 0000 0002 0356"
]

我必须得到所有每月至少使用一次的卡号。

所以我的第一个想法是按月和年对它们进行分组:

return transactionsModel.aggregate([
    $group: 
        _id: 
            year: 
                $year: "$transaction"
            ,
            month: 
                $month: "$transaction"
            
        ,
        results: 
            $push: '$$CURRENT.cardnumber'
        
    ,

]).allowDiskUse(true);

那个查询的答案是这样的:

[

    "_id": 
        "year": 2018,
        "month": 9
    ,
    "results": [
        "1000 0000 0002 0356"
    ]
,

    "_id": 
        "year": 2018,
        "month": 10
    ,
    "results": [
        "1000 0000 0002 0356",
        "1000 0000 0002 0358"
    ]

]

但我不知道之后如何找到每个群体中通用的卡号。

期待回应:

"results": [
        "1000 0000 0002 0356"
 ]

提前感谢您的回答。如果您需要任何其他信息,请询问,我会尽力提供。

【问题讨论】:

【参考方案1】:

您可以将结果相交以获得预期结果

var result = [
  
      "_id": 
          "year": 2018,
          "month": 9
      ,
      "results": [
          "1000 0000 0002 0356"
      ]
  ,
  
      "_id": 
          "year": 2018,
          "month": 10
      ,
      "results": [
          "1000 0000 0002 0356",
          "1000 0000 0002 0358"
      ]
  
  ]
const resultData = result.map(r => r.results)
function intersection(a) 
    if (a.length > 2)
        return intersection([intersection(a.slice(0, a.length / 2)), intersection(a.slice(a.length / 2))]);

    if (a.length == 1)
        return a[0];

    return a[0].filter(function(item) 
        return a[1].indexOf(item) !== -1;
    );

console.log(intersection(resultData))

【讨论】:

【参考方案2】:

你可以使用下面的聚合

db.collection.aggregate([
   "$group": 
    "_id": 
      "year":  "$year": "$transaction" ,
      "month":  "$month": "$transaction" 
    ,
    "results":  "$push": "$$CURRENT.cardnumber" 
  ,
   "$group": 
    "_id": null,
    "result":  "$first": "$results" ,
    "results":  "$push": "$results" 
  ,
   "$project": 
    "results": 
      "$reduce": 
        "input": "$results",
        "initialValue": "$result",
        "in":  "$setIntersection": ["$$value", "$$this"] 
      
    
  
])

Output

[
  
    "_id": null,
    "results": [
      "1000 0000 0002 0356"
    ]
  
]

【讨论】:

【参考方案3】:

下面的实现会得到所有每月至少使用过一次的卡号。

let elements = [
        "_id": 
            "year": 2018,
            "month": 9
        ,
        "results": [
            "1000 0000 0002 0356"
        ]
    ,
    
        "_id": 
            "year": 2018,
            "month": 10
        ,
        "results": [
            "1000 0000 0002 0356",
            "1000 0000 0002 0358"
        ]
    
];

let result = 
    "results": []


let found = [];

function findUsedCardNumbers() 
    elements.forEach(element => 
        let card_numbers = element["results"];
        for (let i = 0; i < card_numbers.length; i++) 
            if (isCardNumberContains(card_numbers[i]) && !found.includes(card_numbers[i])) 
                found.push(card_numbers[i])
            
        
    );
    result["results"] = found;


function isCardNumberContains(card_number) 
    let flag = true
    try 
        elements.forEach(element => 
            flag = (element["results"].includes(card_number)) ? true : false;
            if (!flag) 
                throw BreakException;
            
        );
     catch (e) 

    
    return flag;


findUsedCardNumbers();
console.log(result);

预期结果将是:

"results": [
     "1000 0000 0002 0356"
 ]

【讨论】:

以上是关于$group mongodb 后获取常用元素的主要内容,如果未能解决你的问题,请参考以下文章

在 MongoDB 的聚合管道中获取 $group 之后的输入文档中的字段

mongodb用户权限操作常用命令

mongodb用户权限操作常用命令

计算 MongoDB 中重复元素的数量

mongodb在查找查询后获取第一个元素[重复]

MongoDB的聚合操作