#Updating many-to-many via javascript error

14 messages · Page 1 of 1 (latest)

shell jasper
#

Hi,

I've been able to update m2o fields ok via:

itemService .updateOne(item_id, { item_user { user_id: 9 } })
But if I try updating a m2m in the same fashion:

itemService .updateOne(item_id, { item_tagging: { items_item_id: { // junction collection cat_id: 4 } } })

I get an error stating:

Invalid one-to-many update structure: "items_item_id" is not allowed

I'm not sure why. Should I be concerned that it's saying invalid one-to-many update and not many-to-many?

echo kiln
#

Is this with the SDK or in an extension/hook using the internal services?

shell jasper
#

My bad. I'm working off of near-zero documentation for the extension endpoints whereas the SDK lists all of the Items functions I'm using (updateOne, readByQuery) so I assumed what I was working on had relevance to the javascript SDK, in the context of this question (I also wanted to give poor Tim a break from all my extension questions).

Specifically, this is custom endpoint code. Does the javascript sdk documentation for these item functions not apply to their usage in extensions also?

echo kiln
#

While they are similar they are different, but in this case I am really not for sure about how to structure m2m changes on the related collection from the root. Let me see and I will get back with you or tag someone who can help!

shell jasper
#

Good to know. And thanks for checking. If I should change the tag for this post, let me know.

shell jasper
#

Small bit of progress that raises more questions than answers. I'm Googling for even the tiniest sliver of an example of anyone using updateOne with m2m and found one user mentioning sending an array rather than a straight object. So I changed my syntax to:

.updateOne(item_id, { item_tagging: [{ categories_cat_id: { cat_id: 4 } }] })

Which no longer fails. What it does do, however, is not making sense to me:

It create a brand new item and item_id, and creates a new junction item to connect this new item to the cat item referenced by the cat_id.

I've no idea why it created an item instead of updating the item specified in item_id

nova wharf
#

If you want to update a specific junction item you'll need to provide the junction items ID because it is very possible to have an m2m relate to the same item multiple times.

shell jasper
#

The grand plan in all of this is simply to add a tag/category to an item. Items are collection and Categories are a collection.

It's not that I want to update a junction item. I want to update the item_tagging field for the item with item_id.

If updating the junction collection directly is the way to do this, than that's what I'll do.

I'm unsure, as the logic of whether Directus handles some of the work isn't always clear to me. e.g. Inside the Directus UI, the user would not be aware of interacting with a junction collection.

I do understand what you mean by "it is very possible to have an m2m relate to the same item multiple times". It hadn't even occurred to me as I hadn't run into the scenario yet.

Are you suggesting that I work directly with the junction collection in my calls to updateOne?

#

Or is there any functionality in Directus that, if I supplied an object similar to the above (but with correct syntax) would take care of some of the logic of the junction collection. E.g. this appears to be with the UI is doing.... when supplied with an item_id and a cat_id that the user wants to tag it with, no junction collection is specified. The logic is there already for Directus to handle that in the background.

shell jasper
#

Can I ask - where are others looking to solve these kind of questions? Is it a case of working through the source code and reverse-engineering a solution? For my sake and Directus staff, I don't like to be putting all the weight of solving this on asking questions here.

Google is getting me nowhere. I'm literally searching for updateOne strings and getting back so little that's relevant, even when limiting to github or stackoverflow.

nova wharf
# shell jasper The grand plan in all of this is simply to add a tag/category to an item. Items ...

You don't necessarily have to use the detailed format if you'd prefer not to think about the junction table. The "basic" format allows you to directly deal with children but comes with the drawback of always requiring all children (it will consider the list sent as all children and delete the rest) and can be hard to debug having most of the logic abstracted away https://docs.directus.io/reference/introduction.html#one-to-many-many-to-many

#

Can I ask - where are others looking to solve these kind of questions?
Here and Docs (and the Source for developers i presume)
Google is getting me nowhere.
Yeah there's not a whole lot out there and often things found on gooogle are outdated as v9 is relative new and a complete rewrite from previous versions.

shell jasper
#

Thanks for the update Tim.

My trial and error to get this work went down the route of dealing with the junction collection directly. The following is what I'm using to remove a tag/category in a m2m relationship between Items and Categories
`
let filterData = {
'items_item_id': {
'_eq': item_id
},
'categories_cat_id': {
'_eq': req.body.cat_id
}
}
let parsedFilter = qs.parse(filterData);

// Find the id of the junction collection
// that matches both the item and cat ids

itemCatJunctionService // ItemService for junction collection
.readByQuery({
filter: parsedFilter
})
.then((results) => {
let junction_id = results[0].id;
itemCatJunctionService
.deleteOne(junction_id)
})`

This, on the surface, appears to work as I intended. I'm getting the results I expect.

Before I commit to this, can I ask is there anything (potentially) wrong, with using this method? i.e. calling readByQuery and deleteOne on the junction collection directly rather than through updating the items or categories fields?

Perhaps of interest, but when I used 'readOne' instead of 'readByQuery' I was getting a 'you do not have permission to access this' error. It may be something further back in my own code but I was wondering is there any obvious reason I'd get this error when authenticating as an admin with all permissions?

nova wharf
#

Before I commit to this, can I ask is there anything (potentially) wrong, with using this method? i.e. calling readByQuery and deleteOne on the junction collection directly rather than through updating the items or categories fields?
Nothing wrong with that imo but i would recommend using js const results = await itemCatJunctionService.readByQuery() over chaining .then()'s.
It may be something further back in my own code but I was wondering is there any obvious reason I'd get this error when authenticating as an admin with all permissions?
Probably not a permission error (yeah i know) but a an invalid ID or something as readOne(ID, Query) will require the ID of the junction record you're trying to read