I can't access to the model from creating a smart action

forest/users.js

collection('users', {
  actions: [{
    name: 'isbot',
    fields: [{
      field: 'isBot',
      type: 'Boolean',
      }],
  }],

routes/users.js

const express = require('express');

const { PermissionMiddlewareCreator, RecordsGetter } = require('forest-express-mongoose');

const { users } = require('../models');

const router = express.Router();

router.post('/actions/isbot', permissionMiddlewareCreator.smartAction(), (req, res) => {
  
  const recordsGetter = new RecordsGetter(users, req.user, req.query);

  return recordsGetter.getIdsFromRequest(req)
    .then(userIds => users.updateMany({ _id: { $in: userIds }}, { $set: { isBot: true }}))
    .then(() => res.send({ success: 'done!' }));
});

I got this error when trying to do the action.

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'updateMany' of undefined

Seems like I can’t access the model from the route.

Hey @Kevinn98, and welcome to our community :wave:

Could you please share your project name so I can check your project configuration on my end ?

Thanks in advance :pray:

Hi, the project is Kingdom from Julian Renard account.

@Kevinn98 :wave:

Are you sure about your models/users.js file ? This looks more like a forest/users.js file.

Do you have an associated mongoose model to your users? Thanks in advance

@jeffladiray Oh, my bad yes, that was from my forest file.

And this is from my models/users.js

 const schema = Mongoose.Schema({
    'strategy': String,
    'email': String,
    'alpha': Boolean,
    'balance': {
      type: Mongoose.Schema.Types.Decimal128
    },
    'items': Object,
    'active': Boolean,
    'username': String,
    'onboardingDone': Boolean,
    'kingdoms': [{ type: Mongoose.Schema.Types.ObjectId, ref: 'kingdoms' }], 
    'logs': [
      {
        'event': {
          type: String,
          required: true,
        },
        'metadata': {
          type: Object,
        },
      },
      {
        timestamps: true,
      }
    ],
  },
  {
    timestamps: true,
  });

  return mongoose.model('users', schema, 'users');
};

Finally (Sorry for that) could you also share your models/index.js

The model definition looks like the “old” v7 format, I just want to make sure that the code that import your model does match with forest-express-mongoose v8.

Thanks in advance

Ok sure!

const fs = require('fs');
const path = require('path');
const Mongoose = require('mongoose');

const databasesConfiguration = require('../config/databases');

const connections = {};
const db = {};

databasesConfiguration.forEach((databaseInfo) => {
  const connection = Mongoose.createConnection(databaseInfo.connection.url, databaseInfo.connection.options);
  connections[databaseInfo.name] = connection;

  const modelsDir = databaseInfo.modelsDir || path.join(__dirname, databaseInfo.name);
  fs
    .readdirSync(modelsDir)
    .filter((file) => file.indexOf('.') !== 0 && file !== 'index.js')
    .forEach((file) => {
      try {
        const model = require(path.join(modelsDir, file))(connection, Mongoose);
        db[model.name] = model;
      } catch (error) {
        console.error(`Model creation error: ${error}`);
      }
    });
});

db.objectMapping = Mongoose;
db.connections = connections;

module.exports = db;

Thanks.

I would suggest to console.log(db); at the end of the models/index.js file to make sure users is indeed correctly exported and defined at this stage of the app initialization.

If users model is not displayed in this logs, this may be an export issue.

This is what I got in the log

{
  model: Model { users },
  objectMapping: Mongoose {
    connections: [ [NativeConnection], [NativeConnection] ],
    models: {},
    modelSchemas: {
      'external-transactions': [Schema],
      'internal-transactions': [Schema],
      kingdoms: [Schema],
      offers: [Schema],
      tiles: [Schema],
      users: [Schema]
    },
    options: { pluralization: true, [Symbol(mongoose:default)]: true },
    _pluralize: [Function: pluralize],
    Schema: [Function: Schema] {
      reserved: [Object: null prototype],
      Types: [Object],
      ObjectId: [Function]
    },
    model: [Function (anonymous)],
    plugins: [ [Array], [Array], [Array], [Array] ]
  },
  connections: {
    default: NativeConnection {
      base: [Mongoose],
      collections: [Object],
      models: [Object],
      config: [Object],
      replica: false,
      options: null,
      otherDbs: [],
      relatedDbs: {},
      states: [Object: null prototype],
      _readyState: 2,
      _closeCalled: false,
      _hasOpened: false,
      plugins: [],
      id: 1,
      _listening: false,
      _connectionOptions: [Object],
      '$dbName': 'kingdom',
      name: 'kingdom',
      host: 'localhost',
      port: 27017,
      user: undefined,
      pass: undefined,
      client: [MongoClient],
      '$initialConnection': [Promise],
      then: [Function (anonymous)],
      catch: [Function (anonymous)]
    }
  }
}

There shouldn’t be any model property in this db object according to the models/index.js you shared here :thinking:

On my end, I have the following output on a freshly generated project

My model:

When outputting db in the console

All the files & output you shared here seems stripped.

I’m not sure why your users model is named model in the db object but that’s most likely the reason why updateMany can’t be called on the user object from your smart action.

Do you have any mention in your project of the 'model' string ?

Nope :disappointed_relieved: No mention of that. That’s probably the case also.

Hi @Kevinn98 :wave: it is pretty strange :thinking: Can you give us the version of mongoose and forest-express-mongoose you are using.

Hi, I’m using “forest-express-mongoose”: “^8.3.10” version.

According to this

and using the output you shared, it seems like you have somewhere a model.name which is equal to model.

I would suggest to try console.log where this db[model.name] = model; is computed, just to see what’s going on.