Closed Akeri closed 5 years ago
Which operation are you referring to? For most stuff it's using standard LB queries, so if it works on LB it should work there as well
Hello Michael, thanks for your answer. I give an example:
A model category with an identifier named slug which is a string
{
"name": "Category",
"base": "PersistedModel",
"idInjection": false,
"forceId": false,
"options": {
"validateUpsert": true
},
"mixins": {
"Tree": true
},
"properties": {
"slug": {
"type": "string",
"id": true
},
"name": {
"type": "string"
}
}
}
Attempt to create a root node, then a child node through the parent instance
Category.create({slug: 'category-1', name: 'Category 1'}).then((parentCategory) => {
Category.addNode(parentCategory, {slug: 'category-1-1', name: 'Category 1.1'});
});
Code above create "category-1" successfully, then produces MongoError: unknown operator: $slug
at addNode
operation. The mixin is not treating parentCategory
as a instance because it's expecting an id
property.
Attempt to create a root node, then a child node through the parent identifier (slug property)
Category.create({slug: 'category-1', name: 'Category 1'}).then((parentCategory) => {
Category.addNode(parentCategory.slug, {slug: 'category-1-1', name: 'Category 1.1'});
});
This time it produces TypeError: Cannot read property 'ancestors' of null
at addNode
operation. The mixin generates a {id: value}
criteria when receiving a string as the parent argument, so the parent cannot be found.
Attempt to create a root node, then a child node through a parent criteria
Category.create({slug: 'category-1', name: 'Category 1'}).then((parentCategory) => {
Category.addNode({slug: parentCategory.slug}, {slug: 'category-1-1', name: 'Category 1.1'});
});
It produces Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters
at addNode
operation. This time the mixin succeeds finding the parent from database, then it fails setting the parent property in the child node, because it's attempting to parse it as an ObjectId value, when it's not.
Thanks in advance
Category.create({slug: 'category-1', name: 'Category 1'}).then((parentCategory) => {
Category.addNode({slug: parentCategory.slug}, {slug: 'category-1-1', name: 'Category 1.1'});
});
This should work, but i think that setting the id:true
on the model tells LB that it should be treated as a mongo object which is why you get that error. You could give it a go and look it up via the Category
property instead of slug
Setting id: true
just tells LB that's the property to be used as "primary key", but it's not automatically treated as an ObjectId (https://loopback.io/doc/en/lb3/Model-definition-JSON-file.html#id-properties)
You could give it a go and look it up via the Category property instead of slug
I tested the three ways: parent instance, parent id and parent criteria (Each one throws a different error like I showed). Also tested with a regular ObjectId property, and it works of course, but I have this requirement for a specific model.
The issue is related to the mixin, it requires a model with standard ObjectId property to work, which is fine if you always work that way, but in this case I need a custom identifier in my model.
Got identified the problematic lines.
line 487
//convert plain parent and ancestor strings to ObjectId's
ctx[obj].parent = (typeof ctx[obj].parent.toString !== 'undefined' && ctx[obj].parent.toString) ? DS.ObjectID(ctx[obj].parent.toString()) : DS.ObjectID(ctx[obj].parent);
It's assuming my identifier is an ObjectId
line 363
if (typeof node === 'string') {//Hoping on an id
where.id = node;
}
line 369
else if (typeof node.id === 'object') {//this is the actual node model
return Promise.resolve(node);
}
Both lines are assuming that my identifier is a property named "id"
It can be fixed detecting how is configured the actual identifier property in the model (name and type).
I will try to test a fix when I get time. If I get it working, will send a PR. I just want to check if this solution makes sense to you.
Thanks for your answer!
Cool, when you have a PR ready i'll test and push. Thank you for your time
Hello, thanks for the mixin. I'm trying to use it with a model that has an id like
{"slug": {"type": "string", "id": true}}
The mixin does not work if the id is not an ObjectId named "id". I wonder if you have a workaround. Thanks in advance.