fremail / sequelize-nested-set

Library to store and manage nested set trees using Sequelize
MIT License
40 stars 10 forks source link

getChildren() doesn't return all children, always return 1 less child #34

Closed xuanngo2001 closed 2 years ago

xuanngo2001 commented 2 years ago

For the code below, I expect getChildren() to return Phones and TVs but it only returns Phones.

const { Sequelize, DataTypes, BulkRecordError } = require('sequelize');
const ns = require('sequelize-nested-set');

// Connect to database.
const sequelize = new Sequelize({
    dialect: 'sqlite',
    storage: 'treeorg.sqlite'
});

// Define Tree model.
const Tree = ns(sequelize
                , DataTypes
                , 'Tree'
                , { label: DataTypes.STRING }
                , { //tableName: 'Tree'
                    timestamps: false
                    , hasManyRoots: true
                    , levelColumnName: 'level'
                }
);

sequelize.sync()
    .then(() => {

        (async () => {

            let electronics = new Tree(); electronics.label = 'Electronics';
            electronics = await Tree.createRoot(electronics);

            let phones = new Tree(); phones.label = 'Phones';
            await electronics.reload();
            await electronics.addChild(phones);

                let xiaomi = new Tree(); xiaomi.label = 'Xiaomi';
                await phones.reload();
                await phones.addChild(xiaomi);

            let TVs = new Tree(); TVs.label = 'TVs';
            await electronics.reload();
            await electronics.addChild(TVs);

            // Test getChildren()----------------------------------------
            let children = await electronics.getChildren();
            console.log(children);

        })();

    });

Output

[
  Tree {
    dataValues: { id: 2, lft: 2, rgt: 5, level: 1, rootId: 1, label: 'Phones' },
    _previousDataValues: { id: 2, lft: 2, rgt: 5, level: 1, rootId: 1, label: 'Phones' },
    uniqno: 1,
    _changed: Set(0) {},
    _options: {
      isNewRecord: false,
      _schema: null,
      _schemaDelimiter: '',
      raw: true,
      attributes: [Array]
    },
    isNewRecord: false
  }
]
id  lft  rgt  level  root_id  label      
--  ---  ---  -----  -------  -----------
1   1    8    0      1        Electronics
2   2    5    1      1        Phones
3   3    4    2      1        Xiaomi
4   6    7    1      1        TVs
fremail commented 2 years ago

You need to have an up-to-date electronics object before getting its children. // Test getChildren()----------------------------------------await electronics.reload(); let children = await electronics.getChildren(); console.log(children);

xuanngo2001 commented 2 years ago

Thx @fremail, it works with reload(). Can I know why it is not automatically updated? It is becoming increasingly cumbersome to call reload(). First, it is needed for addChild() and now getChildren().

fremail commented 2 years ago

In real life you don't need to insert and select nodes in the same code/function. Usually we have one method (e. g. API) for adding a node, another method for getting node(s). Calling reload() makes an additional query to DB. If your code is rather complex, it's better to control a number of DB queries. That's why I didn't put reload() inside each function