Mongoose.js Ошибка заклинания: ошибка приведения к числу для значения «{ ‘$ gte’: 1 }» в пути «доступ» для модели «Проект»

#javascript #node.js #mongodb #mongoose

#javascript #node.js #mongodb #мангуста

Вопрос:

Я пытаюсь найти пользователя внутри массива пользователей, у которых тот же идентификатор, что и у моего токена, и доступ больше 1.

для этого я использую следующий код, но я получаю ошибку:

 Project.findOne({ Users: {User: decoded._id, access: { $gte: authStatus }}, _id: id })
        .then((result) => {
            console.log(result)
        })
        .catch((err) => {
            console.log(err)
        });
 

Моя схема:

 const ProjectSchema = new Schema(
{
    Users: [
        {
            User: { type: mongoose.Schema.Types.ObjectId, ref: 'usertemps' },
            access: { type: Number, required: true }
        }
    ],
    name: { type: String, required: true },
    deadline: { type: Date, required: true }
},
{
    timestamps: true
}
);
 

Ошибка приведения к номеру:

     CastError: Cast to Number failed for value "{ '$gte': 1 }" at path "access" for model "Projekt"
    at model.Query.exec (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibquery.js:4371:21)
    at model.Query.Query.then (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibquery.js:4463:15)
    at validateOwner (C:UserstomodOneDriveDokumenterGitHubProject-Manager-ProjectroutesmodulesverifyAccess.js:10:5)
    at C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectroutesproject.route.js:44:33
    at Layer.handle [as handle_request] (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterlayer.js:95:5)
    at next (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterroute.js:137:13)
    at module.exports (C:UserstomodOneDriveDokumenterGitHubProject-Manager-ProjectroutesmodulesverifyToken.js:11:3)
    at Layer.handle [as handle_request] (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterlayer.js:95:5)
    at next (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterroute.js:137:13)
    at Route.dispatch (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterroute.js:112:3)
    at Layer.handle [as handle_request] (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterlayer.js:95:5)
    at C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterindex.js:281:22
    at param (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterindex.js:354:14)
    at param (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterindex.js:365:14)
    at Function.process_params (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterindex.js:410:3)
    at next (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesexpresslibrouterindex.js:275:10) {
  messageFormat: undefined,
  stringValue: `"{ '$gte': 1 }"`,
  kind: 'Number',
  value: { '$gte': 1 },
  path: 'access',
  reason: AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:

    assert.ok(!isNaN(val))

      at castNumber (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibcastnumber.js:28:10)
      at SchemaNumber.cast (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibschemanumber.js:382:12)
      at SchemaNumber.SchemaType.applySetters (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibschematype.js:1075:12)
      at EmbeddedDocument.$set (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibdocument.js:1250:20)
      at EmbeddedDocument._handleIndex (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibdocument.js:1019:14)
      at EmbeddedDocument.$set (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibdocument.js:960:22)
      at EmbeddedDocument.Document (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibdocument.js:150:12)
      at EmbeddedDocument [as constructor] (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibtypesembedded.js:42:12)
      at new EmbeddedDocument (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibschemadocumentarray.js:115:17)
      at DocumentArrayPath.SchemaArray.castForQuery (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibschemaarray.js:485:13)
      at DocumentArrayPath.SchemaType.castForQueryWrapper (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibschematype.js:1477:20)
      at cast (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibcast.js:274:34)
      at model.Query.Query.cast (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibquery.js:4772:12)
      at model.Query.Query._castConditions (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibquery.js:1872:10)
      at model.Query.<anonymous> (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibquery.js:2129:8)
      at model.Query._wrappedThunk [as _findOne] (C:UserstomodOneDriveDokumenterGitHubProject-Manager-Projectnode_modulesmongooselibhelpersquerywrapThunk.js:16:8) {
    generatedMessage: true,
    code: 'ERR_ASSERTION',
    actual: false,
    expected: true,
    operator: '=='
  }
}
 

Возможно ли это сделать таким образом, или я все делаю неправильно?

Надеюсь, кто-нибудь сможет помочь, спасибо за ваше время.

Ответ №1:

Для запроса вложенных полей следует использовать точечную нотацию.

 Project.findOne({
  "Users.User": decoded._id,
  "Users.access": { $gte: authStatus },
  _id: id,
})
  .then((result) => {
    console.log(result);
  })
  .catch((err) => {
    console.log(err);
  });


 

Редактировать:

Чтобы отфильтровать элементы внутри массива и вернуть только те элементы, которые соответствуют определенному условию, вы можете использовать $filter operator

 Project.aggregate([
  { $match: { _id: mongoose.Types.ObjectId(id) } },
  {
    $project: {
      name: 1,
      deadline: 1,
      Users: {
        $filter: {
          input: "$Users",
          as: "user",
          cond: {
            $and: [
              {
                $eq: ["$user.User", mongoose.Types.ObjectId(decoded._id)],
              },
              { $gte: ["$user.access", authStatus] },
            ],
          },
        },
      },
    },
  },
])
  .then((result) => {
    // Aggregate method only returns an array, since we are doing a $match based on _id, 
    // we can take the first element in the array if present
    if (result amp;amp; result.length) {
      console.log(result[0]);
    }
  })
  .catch((err) => {
    console.log(err);
  });
 

Комментарии:

1. Я уже пробовал это, и это не сработало. Проблема в том, что мне нужно найти конкретного пользователя, у которого есть идентификатор, который я ищу, и достаточно высокое значение доступа. Если я использую точечную нотацию, она просто находит любого пользователя с идентификатором и любого пользователя с достаточно высоким значением доступа.

2. @MartinOlesen Насколько я понимаю, вам нужен только Users массив в результате, чтобы пользователи соответствовали условию. Я обновил ответ на основе этого. Пожалуйста, проверьте