amplify-js: Unable to query Many-to-Many Relationship in Datastore. Keep getting Invalid field modelID, model ModelName.
Before opening, please confirm:
- I have searched for duplicate or closed issues and discussions.
- I have read the guide for submitting bug reports.
- I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React
Amplify APIs
DataStore
Amplify Categories
api
Environment information
# Put output below this line
System:
OS: Windows 10 10.0.19042
CPU: (4) x64 Intel(R) Core(TM) i5-4460 CPU @ 3.20GHz
Memory: 1.71 GB / 7.94 GB
Binaries:
Node: 12.18.2 - C:\Program Files\nodejs\node.EXE
Yarn: 1.22.4 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
npm: 6.14.5 - C:\Program Files\nodejs\npm.CMD
Browsers:
Chrome: 89.0.4389.128
Edge: Spartan (44.19041.906.0), Chromium (90.0.818.42)
Internet Explorer: 11.0.19041.1
npmPackages:
@chakra-ui/react: ^1.4.1 => 1.4.1
@emotion/react: 11 => 11.1.5
@emotion/styled: 11 => 11.1.5
@reach/router: ^1.3.4 => 1.3.4
@typescript-eslint/eslint-plugin: ^4.21.0 => 4.21.0 (4.19.0)
@typescript-eslint/parser: ^4.21.0 => 4.21.0 (4.19.0)
aws-amplify: ^3.3.26 => 3.3.26
bundle-optimisations: 1.0.0
dev-404-page: 1.0.0
eslint: ^7.23.0 => 7.23.0 (7.22.0)
eslint-plugin-react: ^7.23.1 => 7.23.1
formik: ^2.2.6 => 2.2.6
framer-motion: 4 => 4.0.3
gatsby: ^3.1.2 => 3.1.2
gatsby-env-variables: ^2.0.0 => 2.0.0
gatsby-image: ^3.1.0 => 3.1.0
gatsby-plugin-gatsby-cloud: ^2.1.0 => 2.1.0
gatsby-plugin-image: ^1.1.2 => 1.1.2
gatsby-plugin-manifest: ^3.1.0 => 3.1.0
gatsby-plugin-offline: ^4.1.0 => 4.1.0
gatsby-plugin-react-helmet: ^4.1.0 => 4.1.0
gatsby-plugin-sharp: ^3.1.2 => 3.1.2
gatsby-source-filesystem: ^3.1.0 => 3.1.0
gatsby-transformer-sharp: ^3.1.0 => 3.1.0
internal-data-bridge: 1.0.0
load-babel-config: 1.0.0
mixpanel-browser: ^2.41.0 => 2.41.0
nanoid: ^3.1.22 => 3.1.22
prettier: 2.2.1 => 2.2.1
prod-404: 1.0.0
prop-types: ^15.7.2 => 15.7.2
react: ^17.0.1 => 17.0.1
react-dom: ^17.0.1 => 17.0.1
react-dropzone: ^11.3.2 => 11.3.2
react-dropzone-uploader: ^2.11.0 => 2.11.0
react-helmet: ^6.1.0 => 6.1.0
react-icons: ^4.2.0 => 4.2.0
typescript: ^4.2.4 => 4.2.4
webpack-theme-component-shadowing: 1.0.0
npmGlobalPackages:
@aws-amplify/cli: 4.47.1
@react-native-community/cli: 4.10.1
aws-cdk: 1.95.2
cors-anywhere: 0.4.4
cp-cli: 2.0.0
eslint-config-airbnb-base: 14.2.0
eslint-plugin-import: 2.22.0
eslint: 7.4.0
expo-cli: 3.22.3
gatsby-cli: 2.19.1
lerna: 3.22.1
rimraf: 3.0.2
Describe the bug
I have 2 model with Many-to-Many Relationship. The 2 model is Order and Product. An Order will have many Product and Product will in many Order.
So I followed this Amplify guide to group the into OrderProducts , Order and Product (Code I state in Reproduction step)
But when I query the OrderProduct model like below, in order to get a List of Products by OrderID:
import { Product, OrderProducts } from '../models';
export const GetAllProductIdByOrderId = async (order) => {
return await DataStore.query(OrderProducts, op => op.orderID("eq", order.id)) // this is actual orderID
}
I get this error:
Error: Invalid field for model. field: orderID, model: OrderProducts
at Object.get (index.js:61)
at eval (dataSource.js:103)
at Function.ModelPredicateCreator.createFromExisting (index.js:94)
at DataStore.eval (datastore.js:582)
at step (datastore.js:43)
at Object.eval [as next] (datastore.js:24)
at fulfilled (datastore.js:15)
Expected behavior
When I query OrderProducts with orderID,
DataStore.query(OrderProducts, op => op.orderID("eq", order.id))
I should get an array of ProductID
Reproduction steps
- In Schema.graphql put this 3 models
type Order @model @key(name: "byStore", fields: ["storeID"]) @auth(rules: [{allow: private, operations: [read, update, create, delete]}]) {
id: ID!
buyer_name: String
order_total_amount: String
products: [OrderProducts] @connection(keyName: "byOrder", fields: ["id"])
created_at: AWSTimestamp
}
type OrderProducts @model @key(name: "byOrder", fields:["orderID", "productID"]) @key(name: "byProduct", fields:["productID", "orderID"]) @auth(rules: [{allow: private, operations: [read, update, create, delete]}]){
id: ID!
orderID: ID!
productID: ID!
order: Order! @connection(fields: ["orderID"])
product: Product! @connection(fields: ["productID"])
}
type Product @model @key(name: "byStore", fields: ["storeID"]) @auth(rules: [{allow: owner, operations: [create, update, delete]}, {allow: public, provider: iam, operations: [read]}]){
id: ID!
product_name: String!
product_price: String!
created_at: AWSTimestamp
orders: [OrderProducts] @connection(keyName: "byProduct", fields:["id"])
}
amplify pushin CLI- Save the
OrderandOrderProductsrelationship like this:
export const CreateOrder = async (buyerPhoneNumber, buyerName, totalAmount, ) => {
return await DataStore.save(
new Order({
"buyer_name": buyerName,
"order_total_amount": totalAmount,
"created_at": getCurrentTimestamp(),
"products": []
})
);
}
export const CreateOrderProductsRelationship = async (orderId, productId, order, product) => {
return await DataStore.save(
new OrderProducts({
"orderID": orderId,
"productID": productId,
"order": order,
"product": product
})
);
}
// save a new Order by using this
/*1st function above */
CreateOrder(buyerPhoneNumber, buyerName, totalAmount)
.then(orderModel => {
console.log(orderModel )
// here save the OrderProducts relationship when successfully make an Order
createProductOrderRelationShip(orderModel , productModel)
}).catch(error => { console.log(error); })
// then save a Order and Product relationship
/*second function above*/
const createProductOrderRelationShip = (product, order) => {
CreateOrderProductsRelationship(order.id, product.id, order, product)
.then(res => {
console.log(res)
}).catch(error => {
console.log(error)
setOrderResult(false)
})
}
- Then I want to get all the Product with an
OrderId, so I query like this:
export const GetAllProductIdByOrderId = async (order) => {
return await DataStore.query(OrderProducts, op => op.orderID("eq", order.id))
}
- But I get this error
Error: Invalid field for model. field: orderID, model: OrderProducts
OrderProducts model have a field or orderID, I triple checked this in DynamoDB. But I can query the by orderID.
Code Snippet
// Put your code below this line.
Log output
// Put your logs below this line
Error: Invalid field for model. field: orderID, model: OrderProducts
at Object.get (index.js:61)
at eval (dataSource.js:103)
at Function.ModelPredicateCreator.createFromExisting (index.js:94)
at DataStore.eval (datastore.js:582)
at step (datastore.js:43)
at Object.eval [as next] (datastore.js:24)
at fulfilled (datastore.js:15)
aws-exports.js
const awsmobile = {
"aws_project_region": "ap-southeast-1",
"aws_cognito_identity_pool_id": "ap-southeast-1:f729257a-e9c1-42dd-81e2-8e48ad2de450",
"aws_cognito_region": "ap-southeast-1",
"aws_user_pools_id": "ap-southeast-1_2dHHzRmON",
"aws_user_pools_web_client_id": "c9j7hv6huv6vm7debfbtulfhq",
"oauth": {},
"aws_user_files_s3_bucket": "coollinksbucket164006-dev",
"aws_user_files_s3_bucket_region": "ap-southeast-1",
"aws_appsync_graphqlEndpoint": "https://ohobeyi2ffc77im3xegzj5w3ny.appsync-api.ap-southeast-1.amazonaws.com/graphql",
"aws_appsync_region": "ap-southeast-1",
"aws_appsync_authenticationType": "AMAZON_COGNITO_USER_POOLS"
};
export default awsmobile;
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
No response
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 3
- Comments: 18 (4 by maintainers)
@iartemiev yup… you ok to closing this…
@iartemiev Your code WORKS!!! FINALLY IT WORKS!!! THANK YOU VERY VERY MUCH
I’d need to see the app code for the components that get rendered in your
/item/product-idview to get a better idea.If this is only happening the first time a user is navigating to this view, most likely DataStore hasn’t finished syncing data to the local store at the time you’re calling
DataStore.query. All DataStore operations (e.g.,save,query,observe, etc.) are performed against the local store, so upon initial visit, the store may be empty, and would therefore return[].You can use the following pattern to eagerly start
DataStoreand then perform your initial query after the sync has completed:Regarding auth, using multiple different authorization types (e.g., Cognito with IAM) was added in aws-amplify@3.4.0, so I’d make sure you’re using that or a later version. You’ll want to refer to this section of the docs: https://docs.amplify.aws/lib/datastore/setup-auth-rules/q/platform/js#configure-multiple-authorization-types
The “No current user” error could be happening because you’re attempting to use DataStore before you’ve signed in / gotten credentials for Cognito or IAM.
@raybotha end up you need to move the enum to the last card of your schema, like this
https://github.com/aws-amplify/amplify-adminui/issues/188#issuecomment-832110950 Not sure in local
schema.graphql, but I tried in Admin UI, it workedAnd I definitely agreed what you say, a lot of simple thing is still not working and no way to see why it didnt work, end up when it happen, it consume a lot of time for the simple thing