参数传入必须是一个缓冲区或字符串12字节或字符串24十六进制字符,而在Node js / javascript使用或条件.&l



我想通过_idownerId从数据库中获取数据,所以我给了OR条件,但得到这个错误

Argument passed in must be a Buffer or string of 12 bytes or a string of 24 hex characters
我的代码如下
var ObjectId = require("mongodb").ObjectId;

const getDetailById = async (req, res) => {
const { id } = req.params;
try {
let detail = await Task.find(
{ $or: [{ ownerId: id }, { _id: ObjectId(id) }] }
).populate("shop");
} catch (err) {
sendError(401, "Cannot get detail by given id", err.message, req, res);
}
};

在这里,我可以通过传递_id从数据库中获取数据,这是24个字符,但当我试图通过ownerId获取数据时,它显示了我这个错误:

Argument passed in must be a Buffer or string of 12 bytes or a string of 24 hex characters

我的输出如下所示

{
"_id": "61483aa5e6dcd5bb6b2c9c58",
"ownerId": "b0jytaonktsc5ghf",
"ownerName": "check demo",
"ownerDescription": "Testing purpose",
"shop": {
"_id": "61483aa5e6dcd5bb6b2c9c55",
"shopName": "Aakash",
"shopPlace": "Mumbai",
"__v": 0
},

"createdAt": "2021-09-20T07:39:17.528Z",
"updatedAt": "2021-09-20T07:39:17.528Z",
"__v": 0
},

这是我的Schema:

const mongoose = require("mongoose");
const uniqid = require("uniqid");
const ownerSchema = new mongoose.Schema(
{
ownerId: {
type: String,
default: uniqid(),
unique: true,
},
OwnerName: {
type: String,           
},
taskTag: [
{
type: String,
},
],
onwerDescription: {
type: String,
},       
shop: {
type: mongoose.Schema.Types.ObjectId,
ref: "peoples",
default: null,
},    
},
{ timestamps: true }
);
const owner = mongoose.model("task", ownerSchema);
module.exports = owner;

问题

  • ObjectId正好有24个十六进制字符或12字节的字符串
  • uniqid库用于生成ownerId生成18字节唯一id

的原因如你所见,这两种格式是不兼容的。结果是这样的:

  1. 您尝试根据uniqid()生成的值查询数据库
  2. $or的第二个参数将尝试基于该值生成ObjectId,由于该格式与ObjectId格式不兼容,它将抛出错误,认为它是ObjectId的无效格式

解决方案您可以使用本机Nodecrypto库更改uniqid库以生成24十六进制字符串,长度为12字节,这将与ObjectId格式兼容。由于它是本机包,您不需要安装它,只需导入并使用它即可。现在,您还可以从项目中删除uniqid包并减少依赖项的数量。

const mongoose = require("mongoose");
const crypto = require("crypto");
const ownerSchema = new mongoose.Schema(
{
ownerId: {
type: String,
default: crypto.randomBytes(12).toString('hex'),
unique: true
},
...
);

问题是ObjectId(id)的调用,因为它不能处理ownerId字符串的输入,只要你传递ownerId。

最干净的解决方案(在我看来)是将ownerId的类型也更改为ObjectId:

const mongoose = require("mongoose");
const uniqid = require("uniqid");
const ownerSchema = new mongoose.Schema(
{
ownerId: {
type: mongoose.Schema.Types.ObjectId,
default: mongoose.ObjectId(),
unique: true,
},
OwnerName: {
type: String,           
},
...

或处理不同的输入,如:

var ObjectId = require("mongodb").ObjectId;
const getDetailById = async (req, res) => {
const { id } = req.params;
let filter = [{ ownerId: id }]
try {
const _id = ObjectId(id);
filter.push({ _id })
} catch () {
// Do nothing
}
try {
let detail = await Task.find(
{ $or: filter }
).populate("shop");
} catch (err) {
sendError(401, "Cannot get detail by given id", err.message, req, res);
}
};

PS:不要忘记执行一些输入验证!永远不要相信用户输入;)

相关内容

最新更新