Skip to content

Cannot get nested field index working with MongoDB #6899

@dulismo

Description

@dulismo

Describe the bug

Example schema :

{
  "name": "users",
  "properties": {
    "email": {
      "type": "string",
      "nullable": true,
      "unique": true
    },
    "firstName": {
      "type": "string"
    },
    "lastName": {
      "type": "string"
    },
    "metaData": {
      "type": "json",
      "nullable": true
    }
  },
  "indexes": [{
    "properties": "metaData.nesTed.field"
  }]
}

When calling schemaGenerator.updateSchema with that schema, the MongoSchemaGenerator raises an error

Cannot read properties of undefined (reading 'fieldNames')

It looks like the MongoSchemaGenerator.createIndexes method searches for metaData.nesTed.field key inside base properties & crashes on meta.properties[prop].fieldNames as no such property exist (which is expected, metaData being a json column).

I could fix this using options :

  "indexes": [{
    "properties": []
    "options": {
      "metaData.nesTed.field": 1
    }
  }]

However, the same fix does not work with uniques as they behave differently than pure indexes.

    "uniques": [
      {
        "properties": [],
        "options": {
          "metaData.auth.id": 1,
          "metaData.auth.provider": 1
        }
      }
    ]

This now raises :

Error in specification { name: "", unique: true, key: {} } :: caused by :: Index keys cannot be empty.

Indeed, the MongoSchemaGenerator.createUniqueIndexes only looks for target properties inside index.properties parameter, index.options parameter is only used for the 2nd MongoDB createIndex parameter.
This is different from indexes where options can be an array of two objects for :

  "indexes": [{
    "properties": [],
    "options": [{
      "metaData.auth.id": 1,
      "metaData.auth.provider": 1,
    }, {
      "unique": true
    }]
  }]

This latest example do work, but I feel like I'm twisting Mikro and that everything would be simpler if I could rely solely on the properties field.

Thanks you !

Reproduction

import { MikroORM, EntitySchema } from '@mikro-orm/mongodb';

const Users = new EntitySchema({
  name: 'Users',
  properties: {
    _id: {
      type: 'ObjectId',
      primary: true,
    },
    email: {
      type: 'string',
      nullable: true,
      unique: true,
    },
    firstName: {
      type: 'string',
    },
    lastName: {
      type: 'string',
    },
    metaData: {
      type: 'json',
      nullable: true,
    },
  },
  indexes: [
    {
      properties: 'metaData.nesTed.field',
    },
  ],
});

let orm: MikroORM;

beforeAll(async () => {
  orm = await MikroORM.init({
    entities: [Users],
    dbName: '6899',
  });
});

afterAll(async () => {
  await orm.close(true);
});

test('GH #6899', async () => {
  await orm.schema.updateSchema();
});

What driver are you using?

@mikro-orm/mongodb

MikroORM version

6.4.16

Node.js version

22

Operating system

MacOS

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions