Closed kenchoong closed 3 years ago
I followed the suggestion from this issue which suggest in order to get all ProductId
in an Order
, I should:
OrderProducts
by orderID
, so I get a list of productID
. productID
to get all product infoWhich I do exactly that. The problem now is I cant get the List of ProductID
using orderID
, cause I get this error Error: Invalid field for model. field: orderID, model: OrderProducts
I also followed this amplify docs, which almost identical with my model, but I still get that error
Somebody please advise, what else I should do.
We have a discussion in amplify discord here
Then I tried to add a queryField
named getOrderByOrderIDByProductID
in OrderProducts
like this:
type OrderProducts @model @key(name: "byOrder", fields:["orderID", "productID"], queryField: "getOrderByOrderIDByProductID") @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"])
}
Then I have tried to query in appsync console:
query MyQuery {
getOrderByOrderIDByProductID(filter: {orderID: {eq: "8649a9da-9ea6-4a30-afe7-6b336a8f853d"}}) {
items {
order {
buyer_name
createdAt
id
}
}
}
}
Then I get the output like this:
{
"data": {
"getOrderByOrderIDByProductID": null
},
"errors": [
{
"path": [
"getOrderByOrderIDByProductID"
],
"data": null,
"errorType": "MappingTemplate",
"errorInfo": null,
"locations": [
{
"line": 2,
"column": 3,
"sourceName": null
}
],
"message": "Expression block '$[query]' requires an expression"
}
]
}
You can followed the conversation discord here
After adding queryField: "getOrderByOrderIDByProductID")
into OrderProducts
@key:
Following step taken:
then I cant import getOrderByOrderIDByProductID
into my files, cause in my model/index.js
files, dont have getOrderByOrderIDByProductID
field exported, therefore I get this error:
warn Attempted import error: 'getOrderByOrderIDByProductID' is not exported from '../models' (imported as 'getOrderByOrderIDByProductID').
Therefore I try to add in myself (not sure right or not, I just try, not sure the correct way)
This is how my model/index.js
file look like after try to add in getOrderByOrderIDByProductID
import { initSchema } from '@aws-amplify/datastore';
import { schema } from './schema';
// of course have other stuff, I remove the non-relevant
// I tried to add getOrderByOrderIDByProductID myself
const { Order, OrderProducts, Product, getOrderByOrderIDByProductID } = initSchema(schema);
export {
Order,
OrderProducts,
Product,
getOrderByOrderIDByProductID
};
Then when I query in my file like this:
import { Product, OrderProducts, getOrderByOrderIDByProductID } from '../models';
export const GetAllProductIdByOrderId = async (order) => {
return await DataStore.query(getOrderByOrderIDByProductID, { filter: { orderID: { eq: order.id } } })
}
I get this error:
error Error: Constructor is not for a valid model
The whole process in start here amplify discord message
The next attempt is check with the appsync console which I mention at previous comment
To summarize, my goal is ONLY ONE.
With the model I shown here, I want to:
Get all productID with a given orderID
I just followed this doc and the suggestion in this issue
Not sure what I doing wrong, please give some help, I just tried a lot of thing but no luck.
Thanks
Any advice on this?? Cause I still didnt see any possible way
I also created an github discussion for this issue https://github.com/aws-amplify/amplify-js/discussions/8175#discussion-3336765
I've also been following the docs on this and it's not clear to me why it's not working. Even though DataStore has been out for a relatively long time, a lot of simple things like these seem to not work.
@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 worked
And 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
@kenchoong, sorry for the delayed response. I have a PR out to add an example to the docs showing how to query M:M relationships. But, the long and short of it is that queries against M:M "joiner" models like this should eagerly load related models, so you can you filter()
on those models directly.
In your specific case:
Get all productID with a given orderID
You would return the products by filtering on order.id
, like so:
const productsFromOrder = (await DataStore.query(OrderProducts))
.filter(op => op.order.id === order.id)
.map(op => op.product);
If you're only interested in getting product ID's from an order ID (or any other javascript-expressible condition), it's a trivial change at this point.
I'm not actually sure if this interferes, but I believe you should also be skipping the orderID
and productID
's in your save method, as they are redundant. Just do this:
return await DataStore.save(
new OrderProducts({
order: order,
product: product
})
);
One last thing to note: Your model depends on multiple authentication modes, which should not have been capable of syncing as of the time this issues was raised. I think it will work now, but I'm actually not 100% sure about that, as I didn't get to testing your auth rules. TLDR: you may have some work to do to verify your auth rules to make syncing work.
@svidgen yup.. this worked, I can confirm that. But the auth rules I think is still a problem, but that will be another issues
Regarding to the auth rule u mention above, @svidgen , I using gatsby and I keep getting this error:
Error in function rejectionHandler in ./node_modules/@pmmmwh/react-refresh-webpack-plugin/client/utils/errorEventHandlers.js:46
Situation is:
in dev
environment(with gatsby develop), it have this error(liked screenshot above), but still have Product
model returned
in production
environment(with gatsby build), totally NOTHING IS RETURNED, totally NOTHING.
This occured when I query this Product
models with the stated @auth rules,
type Product @model @key(name: "byStore", fields: ["storeID"])
@auth(rules: [
# allow owner to CREATE, UPDATE, DELETE, other user List and Get
{allow: owner, operations: [create, update, delete]},
# allow all authenticated user to READ Product model
{ allow: private,provider: iam, operations: [read] },
# allow all unauthenticated user to READ Product model
{allow: public, provider: iam, operations: [read]}]) {
id: ID!
product_name: String!
product_price: String!
product_image_s3_object_key: String!
created_at: AWSTimestamp
storeID: ID!
product_short_id: String!
orders: [OrderProduct] @connection(keyName: "byProduct", fields: ["id"])
}
Query like this (when user not logged in):
export const GetProductByShortId = async (productShortId) => {
return await DataStore.query(Product, product => product.product_short_id("eq", productShortId))
}
with the @auth rule define above. Totally no idea what is it. Cant even search any answer about this.
I asked in amplify discord here and here, for more details can refer that.
Read 100 times in this docs, not sure what I doing wrong.
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.
@iartemiev IT WORKS!!! Finally it works, thank you very much
type Product @model @key(name: "byStore", fields: ["storeID"])
@auth(rules: [{allow: owner, operations: [create, update, delete]},
{ allow: private,provider: iam, operations: [read] },
{allow: public, provider: apiKey, operations: [read]}]) {
By using this @auth rules, the unauthenticated user is able to Read the Product
model.
Thank you for that.
But 1 more problem,
http://my-domain/item/product-id
(which will query the product with product-id) for the FIRST TIME, it unable to query the model, it return nothing. product
data get return. Is this behavior normal?? And how can I avoid this? I want the data is available when unauthenticated user visit link at the First time.
I'd need to see the app code for the components that get rendered in your /item/product-id
view 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 DataStore
and then perform your initial query after the sync has completed:
import Amplify, {DataStore, Hub} from 'aws-amplify';
function App() {
const [products, setProducts] = useState([]);
useEffect(() => {
DataStore.start();
const listener = Hub.listen('datastore', async ({ payload: { event } }) => {
if (event === 'ready') {
getAllProducts();
// initiate subscription with DataStore.observe here, if needed
}
});
return () => {
listener();
};
}, []);
async function getAllProducts() {
const records = await DataStore.query(Product);
setProducts(records);
}
}
@iartemiev Your code WORKS!!!!!!! FINALLY IT WORKS!!! THANK YOU VERY VERY MUCH
@kenchoong that's great to hear! Are you ok with us closing this issue?
@iartemiev yup.. you ok to closing this..
This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.
Looking for a help forum? We recommend joining the Amplify Community Discord server *-help
channels or Discussions for those types of questions.
Before opening, please confirm:
JavaScript Framework
React
Amplify APIs
DataStore
Amplify Categories
api
Environment information
Describe the bug
I have 2 model with Many-to-Many Relationship. The 2 model is
Order
andProduct
. AnOrder
will have manyProduct
andProduct
will in manyOrder
.So I followed this Amplify guide to group the into
OrderProducts
,Order
andProduct
(Code I state in Reproduction step)But when I query the
OrderProduct
model like below, in order to get aList of Products
by OrderID:I get this error:
Expected behavior
When I query OrderProducts with
orderID
,I should get an array of
ProductID
Reproduction steps
amplify push
in CLIOrder
andOrderProducts
relationship like this:OrderId
, so I query like this:OrderProducts
model have a field ororderID
, I triple checked this in DynamoDB. But I can query the byorderID
.Code Snippet
Log output
aws-exports.js
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