Nodejs Mongoose的find $in会把重复的数据合并起来。

Nodejs Mongoose的find $in会把重复的数据合并起来。

比如我有一个id list
var id_list = [54349edca7abe93829ea4449, 54349edca7abe93829ea4449, 5428ee861cab6e635d1927d1]
其中第一个和第二个是一样的。
我使用Model.find({ _id : {$in : id_list} }, function(err, models){})
里面返回的models只有两个数据。 但是我就是想要有三个数据。 有没有简单的办法解决这个问题? 难道我自己还要再构造一遍返回值。
多谢


4 回复

Node.js Mongoose 的 find $in 不会自动去重

问题描述

假设你有一个包含重复 ID 的列表,并且你希望使用 Mongoose 的 find 方法查询这些 ID 对应的文档。然而,当你使用 $in 操作符时,Mongoose 返回的结果中不会包含重复的文档。

例如:

var id_list = [
    '54349edca7abe93829ea4449', 
    '54349edca7abe93829ea4449', 
    '5428ee861cab6e635d1927d1'
];

Model.find({ _id: { $in: id_list } }, function(err, models) {
    if (err) throw err;
    console.log(models.length); // 输出结果为 2,而不是 3
});

在这个例子中,返回的 models 数组中只有两个文档,因为 54349edca7abe93829ea4449 出现了两次,但在查询结果中只出现了一次。

解决方案

如果你确实需要包含重复的文档,可以先进行一次查询,然后手动处理重复的逻辑。一种简单的方法是在查询之前,将数组中的每个元素都添加到结果数组中。

var id_list = [
    '54349edca7abe93829ea4449', 
    '54349edca7abe93829ea4449', 
    '5428ee861cab6e635d1927d1'
];

// 使用一个 Set 来存储唯一值
var uniqueIds = new Set(id_list);

Model.find({ _id: { $in: [...uniqueIds] } }, function(err, models) {
    if (err) throw err;

    // 构造最终的结果数组
    var finalModels = [];
    id_list.forEach(function(id) {
        var model = models.find(m => m._id.toString() === id);
        if (model) {
            finalModels.push(model);
        }
    });

    console.log(finalModels.length); // 输出结果为 3
    console.log(finalModels); // 输出完整的模型数组
});

解释

  1. 使用 Set 去重:首先,我们使用 JavaScript 的 Set 数据结构来去除 id_list 中的重复项。Set 只允许存储唯一的值。
  2. 查询数据库:然后,我们使用 Set 中的唯一值作为查询条件,执行 find 查询。
  3. 手动添加重复项:最后,我们遍历原始的 id_list,检查每个 ID 是否存在于查询结果中。如果存在,则将其添加到最终的结果数组 finalModels 中。

这种方法虽然稍微复杂一些,但能够确保所有指定的 ID(包括重复的)都能被正确地包含在查询结果中。


自己处理吧

var _ = require(‘lodash’); var id_list = [‘54349edca7abe93829ea4449’, ‘5428ee861cab6e635d1927d1’], dup_id = ‘54349edca7abe93829ea4449’; Model.find({ _id : {$in : id_list} }, function(err, docs){ var dup_index = _.findIndex(docs, {id : dup_id}); var dup_doc = _.cloneDeep(docs[dup_index]); // more … });

在使用 Mongoose 的 find 方法时,通过 $in 操作符查询数据库中的文档,如果查询条件中的某些 ID 是重复的,Mongoose 会从数据库中查询出唯一的结果。这是因为 MongoDB 本身只存储唯一的文档记录。

如果你想在查询结果中保留重复的 ID,你需要在客户端处理这些重复项。可以通过在查询后手动处理这些重复项来实现。

以下是一个示例代码,展示如何在查询后处理重复的 ID:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// 假设有一个简单的模型
const MyModel = mongoose.model('MyModel', new Schema({
    name: String
}));

// 示例ID列表
var id_list = [
    '54349edca7abe93829ea4449',
    '54349edca7abe93829ea4449',
    '5428ee861cab6e635d1927d1'
];

// 查询数据库
MyModel.find({ _id: { $in: id_list } }, function (err, models) {
    if (err) {
        console.error(err);
        return;
    }

    // 使用一个新的对象数组来保存查询结果,确保包含重复项
    const resultModels = [];
    const foundIds = [];

    for (let i = 0; i < id_list.length; i++) {
        if (!foundIds.includes(id_list[i])) {
            // 查找与id_list中相同的模型,并添加到结果中
            const model = models.find(model => model._id.toString() === id_list[i]);
            if (model) {
                resultModels.push(model);
                foundIds.push(id_list[i]);
            }
        }
    }

    console.log(resultModels);
});

在这个示例中,我们首先定义了一个包含重复 ID 的数组 id_list。然后,我们使用 find 方法查询数据库。查询结果会过滤掉重复的 ID,我们通过遍历 id_list 并检查是否已经找到了相同的 _id 来确保所有 ID 都被包括在结果中。最后,我们将这些模型保存在一个新的数组 resultModels 中,并输出结果。这样,即使在数据库中存在重复的 ID,你仍然可以得到包含重复项的结果。

回到顶部