【问题标题】:Incorrect output when using lodash on results returned by mongoose对 mongoose 返回的结果使用 lodash 时输出不正确
【发布时间】:2020-03-26 04:55:01
【问题描述】:

我有一个从 mongodb 查询返回的结果集,并且正在使用 lodash 重新格式化它。我正在尝试将对象数组转换为单个对象。问题是当我在结果集上使用 lodash 时,我得到了意外的输出。

注意:在 codepen/codesandbox 上运行 sn-p 会得到正确的输出,但直接从 mongoose 结果中使用时不会。

猫鼬查询

try {
    const petInfo = await pets.find({ userId: user_id, petId: pet_id })
                              .select({
                                  "_id": 0,
                                  "createdAt": 0,
                                  "updatedAt": 0,
                                  "__v": 0
                              });

    if(!petInfo) {
        return res.status(400).json({ message: "FAILED_TO_FETCH_PET_INFO" });
    }

    let newObj = _.reduce(petInfo, (acc, cur)=> { return _.assign(acc, cur) }, {});
    return res.status(200).json(newObj);
}
catch (error) {
    req.errorMsg = error.message; // Log actual error
    return res.status(500).json({ message: "SOME_ERROR_OCCURRED" });
}

猫鼬查找查询的结果 (petInfo)

[
    {
        "age": {
            "days": "",
            "months": "",
            "years": ""
        },
        "userId": "45422605180207851194",
        "name": "Oscar",
        "gender": "FEMALE",
        "type": "Dog",
        "breed": "",
        "weight": "",
        "spayOrNeuter": false,
        "petId": "KSVv7yJLnUWX3n"
    }
]

Lodash sn-p

let newObj = _.reduce(petInfo, (acc, cur)=> { return _.assign(acc, cur) }, {});
return res.status(200).json(newObj);

修改后的结果

{
    "$__": {
        "strictMode": true,
        "selected": {
            "_id": 0,
            "createdAt": 0,
            "updatedAt": 0,
            "__v": 0
        },
        "getters": {
            "age": {
                "days": "",
                "months": "",
                "years": ""
            }
        },
        "wasPopulated": false,
        "scope": {
            "age": {
                "days": "",
                "months": "",
                "years": ""
            },
            "userId": "45422605180207851194",
            "name": "Oscar",
            "gender": "FEMALE",
            "type": "Dog",
            "breed": "",
            "weight": "",
            "spayOrNeuter": false,
            "petId": "KSVv7yJLnUWX3n"
        },
        "activePaths": {
            "paths": {
                "userId": "init",
                "petId": "init",
                "name": "init",
                "gender": "init",
                "type": "init",
                "breed": "init",
                "age.days": "init",
                "age.months": "init",
                "age.years": "init",
                "weight": "init",
                "spayOrNeuter": "init"
            },
            "states": {
                "ignore": {},
                "default": {},
                "init": {
                    "userId": true,
                    "name": true,
                    "gender": true,
                    "type": true,
                    "breed": true,
                    "age.days": true,
                    "age.months": true,
                    "age.years": true,
                    "weight": true,
                    "spayOrNeuter": true,
                    "petId": true
                },
                "modify": {},
                "require": {}
            },
            "stateNames": [
                "require",
                "modify",
                "init",
                "default",
                "ignore"
            ]
        },
        "pathsToScopes": {},
        "cachedRequired": {},
        "session": null,
        "$setCalled": {},
        "emitter": {
            "_events": {},
            "_eventsCount": 0,
            "_maxListeners": 0
        },
        "$options": {
            "skipId": true,
            "isNew": false,
            "willInit": true
        },
        "nestedPath": "age"
    },
    "isNew": false,
    "_doc": {
        "age": {
            "days": "",
            "months": "",
            "years": ""
        },
        "userId": "45422605180207851194",
        "name": "Oscar",
        "gender": "FEMALE",
        "type": "Dog",
        "breed": "",
        "weight": "",
        "spayOrNeuter": false,
        "petId": "KSVv7yJLnUWX3n"
    },
    "$locals": {},
    "$init": true
}

【问题讨论】:

  • 你能显示你的猫鼬查询吗?
  • 当然。等一下。
  • 更新了问题。

标签: javascript node.js mongodb express lodash


【解决方案1】:

这样做的原因是因为 mongoose 不会返回您认为它会返回的对象。相反,它返回一个带有一堆方法等的“猫鼬”对象。有两种方法可以解决这个问题,要么在查询上调用.lean(),要么在结果上调用toJSON(),将结果清理为普通的 js 对象。

.lean()

const petInfo = await pets.find({ userId: user_id, petId: pet_id })
    .select({
        "_id": 0,
        "createdAt": 0,
        "updatedAt": 0,
        "__v": 0
    }).lean();

.toJSON()

const petInfo = await pets.find({ userId: user_id, petId: pet_id })
    .select({
        "_id": 0,
        "createdAt": 0,
        "updatedAt": 0,
        "__v": 0
    }).lean();

const parsed = petInfo.toJSON()

【讨论】:

    【解决方案2】:

    您的查询将以文档对象而不是普通对象的形式返回结果集,这就是为什么您会获得所有其他信息,例如 strictMode、getter 等。

    您可以使用lean() 函数来仅获取普通对象(请参阅https://mongoosejs.com/docs/tutorials/lean.html),例如:

    const petInfo = await pets.find({ userId: user_id, petId: pet_id })
                                          .select({
                                              "_id": 0,
                                              "createdAt": 0,
                                              "updatedAt": 0,
                                              "__v": 0
                                          }).lean();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-14
      • 2020-02-18
      • 2011-06-21
      • 2017-10-05
      • 2012-04-11
      • 2016-02-06
      • 2017-05-09
      • 1970-01-01
      相关资源
      最近更新 更多