New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FeathersVuex returning one row duplicated from a service with an associated table #404
Comments
Can you inspect the store state in the vue dev tools to see if the records are duplicated? |
And does the records have an Id field? Like |
Hi and thanks for the reply, the store state is the one i represented in the actual behavior section |
id is set to 'product_id' |
the actual issue is not the duplication it self , the fact that the other language row/object 'de' as explained in the "expected behavior" section that is missing , while substituting the expected result with a duplicate of the first result another Q i have in mind does feathersvuex strict to get unique IDs as a result , since the associated (joined) tables result obviously does not have a unique ID , |
I don't quite have full clarity of what's going on here. If you have the |
Hi , Thanks Marshal for your explanation select a.product_id, a.product_code, b.product, b.lang_code from products as a inner join productsdescriptions as b ON a.product_id = b.product_id since am joining the two tables i will not get a unique product_id because the same product can be stored in different langs, now : Feathers-Vuex is not |
If they have the same |
Actually i should be pulling 2 records with the same Product_id but 2 different Lang_code (en, de) , what i am getting in the store is the same product_id for the same lang_code (en,en) but it should be 2 records for the same product with different languages (en,de,....) |
You have |
And the bug is that you should only see one record. |
Feathers-Vuex does not have any method of interpreting the results of an SQL join when multiple records have the same id. The solution in your case would be to either
The second solution is how I would personally handle this. But I don't know the rest of your app. |
Actually, the scenario where having duplicated records is NOT a bug is if you are directly using the results of a |
I am surprised that feathers-vuex acts as a filtering proxy to ensure uniqueness of records , in my humble opinion it should behave as a transparent channel , same as it would be the case of calling a REST API , or Feathers-Sockets |
The second solution is feasible with mongodb , incase of using feathers-sequelize with association i think it means extra after hook shaping , which means an overhead |
I appreciate your feedback. The reason this will not work is that I imagine that the overhead from shaping even thousands of records would be immaterial. You could also make an additional request for the relationships. Using |
OR... you could set another field as the |
That last idea is definitely not the way I would handle any relationship because it's a workaround that would likely lead to frustration with more workarounds in the future. |
I really appreciate your help, i shall check and hope to have a viable solution back |
this is a clever idea, i guess , setting the PK as id in the first table while maintaining product_id as an FK might get things sorted i hope |
I believe the most logical solution, after knowing more how feathers-vuex works and with minimal overhead , is to send the request to server to fetch a single language at a time , according to user interaction with a combo to select language. |
Oh, setting the primary key as the It will really simplify the way you handle the related records if you keep them in a place where they can be easily separated out, not tightly coupled in the response. If you have the schema more like this: const product = {
id: 1,
descriptions: [
{ id: 1, lang: 'en', text: 'Back pack' },
{ id: 2, lang: 'es', text: 'Mochila' }
]
} It becomes really easy to edit the description records when you set them up with their own service and Model. At that point, if you put a setupInstance(product, { models }) {
if (product.descriptions) {
product.descriptions = product.descriptions.map(d => models.api.ProductDescription(d))
}
return product
} This will allow you to edit a description using model methods: const english = product.descriptions.find(d => d.lang === 'en')
english.description = 'Backpack'
english.save() // sends request to patch the english description. |
just as a reference , and if any one else needed this assuming feathers-sequelize, I have tested setting raw: false , in the before hook on server , it will shape the result according to your suggested 2nd point (i.e join the records on a sub-key inside the original instead of merging them into a flat array.)
|
Ah. That makes things much simpler. Thanks for the update, @Trioinsight! |
I've added a note about "handling Sequelize joins" to the common patterns section of the docs. It links to this issue. Thanks @Trioinsight for sharing with the community! |
Description
First table: products
Product_id (PK), Product_code, ....
second table: productdescriptions
id (PK), product_code, lang_code, name,....
products model: products has many productdescriptions , FK: 'product_id'
products hook: included productdescriptions , raw:true, and returned context
using feathers-sequelize & mysql
Steps to reproduce
used different techniques renderless componenets, example from common patterns Actions return reactive store records
also tried this in vue component from model docs
created() {
const { Product } = this.$FeathersVuex.api
Product.find({ query: {product_id:6} }).then(/* ... */)
}
computed: { todoss () {
const { Product } = this.$FeathersVuex.api
return Product.findInStore({ query: {} }).data
}
Expected behavior
it should return all products with different lang codes example :
"data": [
{
"product_id": 6,
"product_code": "T0006UROBG",
.....
"Productdescriptions.id": 7,
"Productdescriptions.product_id": 6,
"Productdescriptions.lang_code": "de",
"Productdescriptions.product": "Toshiba 32C120U 32" Class 720P HD LCD TV"
},
{
"product_id": 6,
"product_code": "T0006UROBG",
.....
"Productdescriptions.id": 8,
"Productdescriptions.product_id": 6,
"Productdescriptions.lang_code": "en",
"Productdescriptions.product": "Toshiba 32C120U 32" Class 720P HD LCD TV"
}
]
to double check server is correctly configured
http://localhost:3030/products?product_id=6 returns expected result
also using feathers-client socket directly in vuejs returned the expected result
socket.emit('find', 'products', { product_id:6}, (error, data) => {.....
Actual behavior
[{"product_id":6,"product_code":"T0006UROBG",...
"Productdescriptions.id":8,"Productdescriptions.product_id":6,"Productdescriptions.lang_code":"en","Productdescriptions.product":"Toshiba 32C120U 32" Class 720P HD LCD TV"},{"product_id":6,"product_code":"T0006UROBG",.....
,"Productdescriptions.id":8,"Productdescriptions.product_id":6,"Productdescriptions.lang_code":"en","Productdescriptions.product":"Toshiba 32C120U 32" Class 720P HD LCD TV"}]
System configuration
"@feathersjs/authentication-client": "^4.4.3",
"@feathersjs/feathers": "^4.4.3",
"@feathersjs/socketio-client": "^4.4.3",
"feathers-hooks-common": "^4.20.7",
"feathers-vuex": "^3.2.1",
"vue": "2.5.22",
NodeJS version:
v12.13.0
feathers server:
"@feathersjs/authentication": "^4.4.3",
"@feathersjs/authentication-local": "^4.4.3",
"@feathersjs/authentication-oauth": "^4.4.3",
"@feathersjs/configuration": "^4.4.3",
"@feathersjs/errors": "^4.4.3",
"@feathersjs/express": "^4.4.3",
"@feathersjs/feathers": "^4.4.3",
"@feathersjs/socketio": "^4.4.3",
"@feathersjs/transport-commons": "^4.4.3",
"compression": "^1.7.4",
"cors": "^2.8.5",
"feathers-authentication-hooks": "^1.0.1",
"feathers-sequelize": "^6.1.0",
"helmet": "^3.21.2",
"mysql2": "^2.0.2",
"sequelize": "^5.21.3",
"serve-favicon": "^2.5.0",
The text was updated successfully, but these errors were encountered: