MongoDB - 查找一组文档之间的公共值计数

时间:2017-12-06 22:21:34

标签: javascript arrays mongodb mongodb-query

我有两个字段的文件,我想找到同一组(类别)行之间的公共值计数:例如。

当前数据看起来像这样(假设采用Json格式):

enter image description here

我需要像这样的输出

enter image description here

将不胜感激任何指导/指示。感谢

1 个答案:

答案 0 :(得分:1)

首先,以对象数组的形式获取数据。然后,我们可以使用以下算法来获得您需要的内容:

  1. 获取唯一类别["Music", "Film", "History", "Science"]
  2. 获取这些类别[["Music", "Film"], ["Music", "History"], ["Music", "Science"], ["Film", "History"], ...]
  3. 的组合
  4. 创建类别名称到该类别中包含的书籍的映射。我们可以使用Set来确保值是唯一的。地图的结构类似{"Music": Set("A", "B"), "Film": Set("A", "B", "C"), "History": Set("C", "B"), "Science": Set("C")}
  5. 使用刚刚创建的对象和数组来查找组合之间的重复项。
  6. 完成所有操作后,您将拥有一个具有以下结构的数组:[ [cat1, cat2, [bookInCommon1, bookInCommon2]], [cat1, cat3, [bookInCommon1, bookInCommon2]], ...]
  7. 运行下面的代码以查看它的实际效果。 mongoData保存从Mongo获取的数据。

    const mongoData = [{
        category: "Music",
        book: "A"
    }, {
        category: "Music",
        book: "B"
    },{
        category: "Music",
        book: "A"
    },{
        category: "Film",
        book: "A"
    },{
        category: "Film",
        book: "A"
    },{
        category: "Film",
        book: "B"
    },{
        category: "Film",
        book: "C"
    },{
        category: "Film",
        book: "C"
    },{
        category: "Film",
        book: "A"
    },{
        category: "History",
        book: "C"
    },{
        category: "History",
        book: "C"
    },{
        category: "History",
        book: "B"
    },{
        category: "History",
        book: "B"
    },{
        category: "Science",
        book: "C"
    },{
        category: "Science",
        book: "C"
    },{
        category: "Science",
        book: "C"
    }];
    
    // Step 1: Get the categories
    const categories = Array.from(new Set(mongoData.map(x => x.category)));
    
    // Step 2: Get combinations of those categories
    const combos = [];
    for(let i = 0; i < categories.length - 1; i++) {
    
        let outerCat = categories[i];
    
        for(let j = i + 1; j < categories.length; j++) {
    
            let innerCat = categories[j];
    
            combos.push([
                outerCat,
                innerCat
            ]);
        }
    }
    
    // Step 3: Map the categories to the books that they contain
    const catBooks = mongoData.reduce((map, entry) => {
    
        map[entry.category] = map[entry.category] || new Set(); 
        map[entry.category] = map[entry.category].add(entry.book);
    
        return map;
    
    }, {});
    
    // Step 4: Get the duplicate books for each combo
    combos.forEach((combo, index) => {
        
        const cat1 = combo[0];
        const cat2 = combo[1];
    
        const cat1BooksArr = Array.from(catBooks[cat1]);
        const cat2BooksSet = catBooks[cat2];
    
        const dupes = cat1BooksArr.filter(book => {
            return cat2BooksSet.has(book);
        });
    
        combos[index].push(dupes); // push into combos array
    });
    
    // Done! Your combos array contains arrays that look like this: [cat1, cat2, [dupes]]
    combos.forEach(combo => {
        console.log("Combo: " + combo[0] + ", " + combo[1]);
        console.log("\tNumber of dupes: " + combo[2].length); 
    });