Giter Site home page Giter Site logo

vikpe / mongoose-mpath Goto Github PK

View Code? Open in Web Editor NEW
67.0 3.0 16.0 2.01 MB

Mongoose plugin for tree hierarchy using the materialized path pattern.

Home Page: https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

License: MIT License

JavaScript 100.00%
mongoose mongoose-plugin materialized-path mongodb hierarchical-data node

mongoose-mpath's Issues

Please help with .getParent() function

So i have an array of categories through which i'm looping in pug. There i need to display also parent category name. So when i do
each category, i in categories #{category.getParent()}
it prints just "Object Object" etc...
What can i do to get the category title and some other information?

getChildrenTree method returns an empty object (using mongoose-mpath v2.0.4)

i have this model

const mongoose = require('mongoose'); 
//import MpathPlugin from 'mongoose-mpath';
const MpathPlugin = require('mongoose-mpath')

const Schema = mongoose.Schema;
const CategorySchema = new Schema({ 
    name: { 
        type: String,
        unique: 'The name of the category should be unique',
        required: 'name cannot be blank' 
    },
}).plugin(MpathPlugin,[{
        pathSeparator: '#',              // String used to separate ids in path
        onDelete: 'REPARENT',       // 'REPARENT' or 'DELETE'
        idType: Schema.ObjectId   // Type used for model id
    }]
  );

mongoose.model('Category', CategorySchema); 

and this controller

exports.getChildrenTrees = function(req, res) {  
    category=req.category
    const args = {
        options: {lean: false},

      }
   // const category = new Category(req.body);
    const cat = category.getChildrenTree(args);
    res.status(200).json(cat);
    console.log('All children '+ typeof(cat)); 
  
}

when i call this server method, it reurns an empty array i have tried evrything but same result need a solution if one has had this issue please

[Question] can i assign parent to a doc only by id?

in the readme examples we see a way to assign a parent when im passing the full doc to the query.
what if im trying to assign a parent only by a given id (mongoose id).
should i fetch the full doc (by the given id) and add the doc to the parent key?

Question: Why children attribute is always empty

Greetings,

The plugin is wonderful and you have my apologies. I've implemented the example from the Readme file:

const europe = new LocationModel({name: 'europe'});
const sweden = new LocationModel({name: 'sweden', parent: europe});
const stockholm = new LocationModel({name: 'stockholm', parent: sweden});
const skansen = new LocationModel({name: 'skansen', parent: sweden});
const subSkansen = new LocationModel({name: 'subSkansen', parent: skansen});

await europe.save();
await sweden.save();
await stockholm.save();
await skansen.save();
await subSkansen.save();

I can't understand: What's the benefit children property to be stored in the db collection set with empty value:

Screen Shot 2020-11-21 at 1 12 06 AM

I'm not an expert with this plugging. What I found: The children property is a valuable asset in the following example:

const location = await LocationModel.findOne({name: 'europe'});
const tree = await location.getChildrenTree({});
console.log('location tree', tree[0]);

The response is:
Screen Shot 2020-11-21 at 1 00 06 AM

My questions are: level is a virtual property which is nice.
#1 Why children attribute is not a virtual property ?
#2 Why children attribute is stored as an empty array in the database ?

TypeError: Cannot read property 'length' of undefined

Hello,

When creating a document with an existing parent, i'm getting the following error:

TypeError: Cannot read property 'length' of undefined
    at onStreamData (C:\...\node_modules\mongoose-mpath\lib\mpath.js:46:81)
    at C:\...\node_modules\stream-worker\stream-worker.js:63:39

mpath tries, in preSave, to updateChildPaths of the recently created document, with an undifined pathToReplace, because document.path is not set yet.

There is a simplified way i'm doing the creation:

...
  study.state = 'Published';
  study.save()
    .then(async (savedStudy) => {

            try {
              var s = new Study({
                name: 'blabla',
                state: 'Published',  
                parent: study,
              })
              await s.save()
            } catch (e) {
              console.log(e);
            }
        return res.json(savedStudy)
      })

the study document already has a correct path attribute

I temporaly fixed my problem replacing mpath.js line 67 by:
if (!this.isNew && hasModifiedParent) { // Rewrite child paths when parent is changed

Am I doing something wrong during creation?

Thanks,
Paul

How to dynamically set the parent?

Hi, exists some way to dynamically set the parent or change the parent?

Imagine this:

  • Father 1
    -- Child
    --- Another Child
  • Father 2

I need to change the child from Father 1 to Father 2.

Thanks.

Question: How can you store the count/length of child nodes in parent Model?

Hi, given the example of a twitter clone how would you store the number of replies in each tweet?

Example of Tweet model:

const TweetSchema = new Schema({
  content: {
    type: String,
    default: "",
    required: true,
  },
  author: { type: Schema.Types.ObjectId, ref: "user", required: true },
  replies: {
    type: Number,
    default: 0,
  },
  likes: {
    type: Number,
    default: 0,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

Example of query:

try {
    const tweetParent = await Tweet.findById(req.params.id).populate(
      "author",
      "-password"
    );
    const tweetChildren = await tweetParent
      .getImmediateChildren({})
      .populate("author", "-password");
    
    res.json({ tweets: [tweetParent, ...tweetChildren] });
  } catch (err) {
    res.json(err);
  }

My initial idea was to write a split function that splits the path values by the "#" char and stores the result in a arr and then call arr.length - that way when the Plugin handles reparenting the replies will update. However I cannot get this to work.

Any ideas?

.npmrc with engine-strict=true

hi , i got some problem using .npmrc with engine-strict=true

npm ERR! code EBADENGINE
npm ERR! engine Unsupported engine
npm ERR! engine Not compatible with your version of node/npm: [email protected]
npm ERR! notsup Not compatible with your version of node/npm: [email protected]
npm ERR! notsup Required: {"node":"~0.10.0"}
npm ERR! notsup Actual: {"npm":"9.5.0","node":"v18.15.0"}

can you help to make it support for engine-strict=true
thanks,

Question: How to use DELETE to remove all immediate children?

Hello when using this libarary and attempting to remove a parent node with children I would assume REPARENT would move child nodes up a level to the nearest ancestor and DELETE would remove children of the parent node. However, both DELETE and REPARENT do the same thing in that context.

How can I remove all children of a parent node instead of moving them up to nearest ancestor?

I can provide code examples if neccessary. Thanks for this awesome library!!!!!

Cursor() issue on model find

I am getting an error here:

var childCursor = self.model(this.constructor.modelName).find({parent: this._id}).cursor();

it says that the cursor function is not defined. I have changed to stream() and it works fine.

Do you know why is that a problem? Thanks

getChildrenTree does not return mongoose documents

Hi, there

I use this plugin for tree structure, I can insert a node to the tree. The path and parent fields work as expected.

But, when I use this model to output the tree as json, the framework tell me

Cannot set property 'rootDoc' of undefined

I use .find to get a model array, so I use department[0] as the model. (Sorry for the issue title, I can't modify it now)

Any advice for this situation?

async findAll() {
    const department = await this.ctx.model.Department.find({ isTop: true }).exec();
    const data = await department[0].getChildrenTree();
    return data;
  }

modal

'use strict';

module.exports = app => {
  const mongoose = app.mongoose;
  const objectId = mongoose.Schema.Types.ObjectId;
  const DepartmentSchema = new mongoose.Schema({
    label: {
      type: String,
      require: true,
      unique: true
    },
    isTop: {
      type: Boolean,
      require: true,
      default: false,
    },
    isDepartment: {
      type: Boolean,
      require: true,
      default: true,
    },
    code: {
      type: String,
    },
    orderNum: {
      type: Number,
    },
    manager: {
      type: objectId, ref: 'User',
    },
    viceManager: {
      type: objectId, ref: 'User',
    },
    state: {
      type: Boolean,
      default: true,
    },
    comment: {
      type: String,
    },
  });
  DepartmentSchema.plugin(require('mongoose-mpath'));

  return mongoose.model('department', DepartmentSchema);
};

ERROR while serializing: TypeError: Converting circular structure to JSON

This is my schema

const documentSchema = mongoose.Schema({
  name: {type: String, unique: true},
  tags: [String],
  files: [String],
  business: {type: Schema.Types.ObjectId, ref: 'Business'}
}, {timestamps: true})

documentSchema.plugin(require('mongoose-mpath'))
module.exports = mongoose.model('Document', documentSchema)

when I doing the following I am getting error:

Document.findById(req.params.id, (err, doc) => {
    if(err){
      return next(err)
    }
    const ancestors = doc. getAncestors({})
    **res.json({message: 'ancestors', path: ancestors})**
  })

ERROR===:

TypeError: Converting circular structure to JSON
at JSON.stringify ()

Please let me know if you see any issue in my code. Thanks in advance.

Unable to sort results by path from database queries

Hi,

That's a really promising implementation of materialized paths. Nice work!
I am facing an issue. Currently the generated path of each document includes also it's ID. This makes it impossible to sort documents by an other field. There is no way to sort two documents of the same parent. Removing the last ID from the path will allow to sort properly in our queries with something like that:
sort: { path: 1, ordering: 1 }
Or:
sort: { path: 1, title: 1 }

I hope this makes sense.

Regards

[Help] Help to understand why no childrens are being returned

I have this document:

// root category 

{
  "_id" :  "5be554c8cd98f607feb9b081",
  "title" : "Root",
  "path" : "5be554c8cd98f607feb9b081",
  "value" : "5be554c8cd98f607feb9b081",
  "__v" : 0
}

// parent
 {
            "weight": 0,
            "_id": "5be5561b89f9dc08305b9cbc",
            "title": "Parent",
            "parent": "5be554c8cd98f607feb9b081",
            "path": "5be554c8cd98f607feb9b081/5be5561b89f9dc08305b9cbc"
            "__v": 0
        },
 // children

{
            "_id": "5be55877044ada0873148b6e",
            "title": "Children 1",
            "parent": "5be5561b89f9dc08305b9cbc",
            "path": "5be554c8cd98f607feb9b081/5be5561b89f9dc08305b9cbc/5be55877044ada0873148b6e"
        },
// children of children
     {
            "weight": 0,
            "_id": "5be55c58e848c908e0d061f2",
            "title": "Children of Children 1",
            "parent": "5be55877044ada0873148b6e",
            "path": "5be554c8cd98f607feb9b081/5be5561b89f9dc08305b9cbc/5be55877044ada0873148b6e/5be55c58e848c908e0d061f2",
            "__v": 0
        }

I run this query:

router.post('/categories', (req, res) => {
    const {category, parent} = req.body;

    let args         = {
        filters           : { parent: parent},  //  5be5561b89f9dc08305b9cbc Parent id
        options  : {lean: true},
        minLevel : 3,
    };

    Category.findOne({title: category // 'God' }).exec()
            .then(result => {
                result.getChildrenTree({}).then(categories => {
                        result.getChildrenTree(args).then(children => {
                            res.json({
                                adType      : categories,
                                children     : children,
                            });
                        })
                }).catch(err => console.log(err));
            });
});

The above results to the following response:

{
    "adType": [
        {
            "weight": 0,
            "_id": "5be5561b89f9dc08305b9cbc",
            "title": "Parent",
            "parent": "5be554c8cd98f607feb9b081",
            "path": "5be554c8cd98f607feb9b081/5be5561b89f9dc08305b9cbc",
            "value": "5be554c8cd98f607feb9b081/5be5561b89f9dc08305b9cbc",
            "__v": 0
        },
    ],
    "children": [
        {
            "_id": "5be55877044ada0873148b6e",
            "title": "Children 1",
            "parent": "5be5561b89f9dc08305b9cbc",
            "path": "5be554c8cd98f607feb9b081/5be5561b89f9dc08305b9cbc/5be55877044ada0873148b6e",
            "children": []
        }
]

Why do i get an empty array in "children" : [] and not the Children of Children 1 document?

typescript

How can i use with typescipt in nestjs?

Doesnt save children in node

Hi, seems it doesnt save the children with mongoose

5.13.7

const organisationNode = new this.organisationNode({
  _id: new Types.ObjectId(),
  name,
  parent: rootNode,
  originalId
});
rootNode.save();
return organisationNode.save();

no children can be seen in rootnode

Methods return plain objects instead of mongoose documents?

Not 100% sure but I believe that getChildrenTree method is returning plain objects instead of mongoose documents.

If I use collection.find() then it returns an array of mongoose documents where for example all instance methods are available. If I use collection.getChildrenTree(), the instance methods are not available.

Path update

Hi, thanks for the nice plugin, I am completely new to mongo/mongoose and therefore happy to have your package. I would like to add new parents to existing nodes and also rearrange/add nodes to the tree. Is the updating of the path supported when I delete a node or add a parent? Currently I tried to add/delete node but the path does not update like stated in the docu :/ Maybe I am doing something wrong?
Thanks!

image

Can i create children of different type modelSchema document

//codeword schema

const mongoose = require('mongoose');
const MpathPlugin = require('mongoose-mpath');

const codewordSchema = new mongoose.Schema({
    _id: mongoose.Types.ObjectId,
    tag: String,
    active: { type:Boolean, default: true },
    resToAssigned:[{type: Number}]
});
// add plugin
codewordSchema.plugin(MpathPlugin);

const Codeword = mongoose.models.Codeword || mongoose.model('Codeword', codewordSchema);
module.exports = Codeword ;

//folder schema

const mongoose = require('mongoose');
const MpathPlugin = require('mongoose-mpath');
const Codeword = require('./codeword.model');

const folderSchema = new mongoose.Schema({
    _id: mongoose.Types.ObjectId,
    name: String,
    codewords: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Codeword' }]
});
// add plugin
folderSchema.plugin(MpathPlugin);

const Folder = mongoose.models.Folder || mongoose.model('Folder', folderSchema);
module.exports = Folder;

here i want to make tree like

folder=>children[ folder && codeword ]
like folder file tree structure folder can hold folder and file
but when i am going to create as codeword children of folder like this=>

const parent = await Folder.findOne({ _id: user.rootId });
        const newcodeword = new Codeword({
            _id: new mongoose.Types.ObjectId(),
            tag: codeword,
            parent:parent
        }).save(async (err, result) => {
            if (!err) {
                const tree = await parent.getChildrenTree({ populate: 'codewords', options: { lean: false } });
                console.log({ tree });
            } else {
                console.log(err);
            }
});

This code give me error
TypeError: Cannot read property 'path' of null\n at C:\Users\Admin\Desktop\Working\SB\node_modules\mongoose-mpath\lib\mpath.js:140:37
I think , i can't create a children of different type modelSchema document. I am right if not right , how can i create children of folder as codeword

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.