Skip to content
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

Using Search query on a float field returning unexpected results. #866

Open
2 of 9 tasks
jeff-accountably opened this issue Apr 28, 2022 · 6 comments · May be fixed by #874
Open
2 of 9 tasks

Using Search query on a float field returning unexpected results. #866

jeff-accountably opened this issue Apr 28, 2022 · 6 comments · May be fixed by #874
Assignees
Labels

Comments

@jeff-accountably
Copy link

Description

Here is my example query code running in javascript on the client side.

return useGraphQLQuery(
    {
      filter: {
        transactionTotalAmount: { eq: 29 },
      },
      sort: {
        direction: "desc",
        field: "transactionDate",
      },
      limit: 10,
    },
    searchTransactions,
    "searchTransactions"
  );

My schema has the field as a float, and the model object is tagged with @searchable.

In my database I have a number of transactions that are 29.98, or 29.37, etc. They all get returned from this query, which is unexpected, since only 29 should be returned.

If I change the filter to be transactionTotalAmount: { eq: 29.98 } nothing gets returned, even though that should be an exact match with the transaction that is 29.98.

Categories

  • Analytics
  • API (REST)
  • API (GraphQL)
  • Auth
  • Authenticator
  • DataStore
  • Storage

Steps to Reproduce

No response

Screenshots

No response

Platforms

  • iOS
  • Android

Android Device/Emulator API Level

No response

Environment

ReactJS

Dependencies

N/A

Device

N/A

OS

N/A

CLI Version

8.0.3

Additional Context

No response

@Jordan-Nelson
Copy link

Hi @jeff-accountably - It looks like you are using Amplify JS with react native. Please let me know if that is not the case. Otherwise I will transfer this to the Amplify JS repo.

@Jordan-Nelson Jordan-Nelson transferred this issue from aws-amplify/amplify-flutter Apr 28, 2022
@jeff-accountably
Copy link
Author

I am using Amplify JS with React JS, not react native.

@majirosstefan
Copy link

majirosstefan commented Jul 7, 2022

I am experiencing similar @searchable related error #1038 (maybe it's something with encoding ??)

@ncarvajalc
Copy link
Contributor

Description

The problem could be reproduced and another error appeared in the process, in which AWSDate data would not be sortable or appear in the search results when using the searchTransactions query when using a date with a timezone. This happened using a model with the @searchable directive.

Steps to reproduce errors

  1. Create the following Schema
type Transaction @model @searchable {
  id: ID!
  name: String!
  transactionDate: AWSDate
  transactionTotalAmount: Float
}
  1. Upload it to the cloud
  2. Run the following mutation:
mutation createIncorrect {
  createTransaction(input: {name: "Lorem ipsum dolor sit amet",
          transactionDate: "2010-09-28Z",
          transactionTotalAmount: 123}) {
    name
    transactionDate
    transactionTotalAmount
    id
    createdAt
    updatedAt
  }
}

In your Amazon Open Source service you should see the following index being created:
Pasted image 20220928180237

Notice that the transactionDate is being parsed as a text and that the transactionTotalAmount is being parsed as a long.

  1. Try running the following query:
query filterAndSort {
  searchTransactions(filter: {transactionTotalAmount: {eq: 123}},
  sort: {direction: desc, field: transactionDate}, limit: 10) {
    total
    items {
      id
      transactionDate
      createdAt
      transactionTotalAmount
    }
  }
}

You should see the following result:

{
  "data": {
    "searchTransactions": {
      "total": null,
      "items": []
    }
  }
}

If you change the sort field to name like this:

query filterAndSort {
  searchTransactions(filter: {transactionTotalAmount: {eq: 123}},
  sort: {direction: desc, field: name}, limit: 10) {
    total
    items {
      id
      transactionDate
      createdAt
      transactionTotalAmount
    }
  }
}

You should now see the transaction you had created earlier.
5. Create 1 more transaction with transactionTotalAmount as the same integer part as the one created previously (123) but with a decimal part (.15 in this case):

mutation create {
  createTransaction(input: {name: "Lorem ipsum dolor sit amet",
          transactionDate: "2010-09-28Z",
          transactionTotalAmount: 123.15}) {
    name
    transactionDate
    transactionTotalAmount
    id
    createdAt
    updatedAt
  }
}

Run the previous query:

query filterAndSort {
  searchTransactions(filter: {transactionTotalAmount: {eq: 123}},
  sort: {direction: desc, field: name}, limit: 10) {
    total
    items {
      id
      transactionDate
      createdAt
      transactionTotalAmount
    }
  }
}

And you should see both the result for the first transaction and the second one, even though the second one doesn't have a {transactionTotalAmount: {eq: 123} (equal to 23).

How to solve it

Clone your current environment and be sure that the first element you insert has a transactionDate in the format YYYY-MM-DD. If you insert the Z at the end it will be parsed as text and won't let you sort by date, even if allowed by the AWSDate Scalar. Also be sure to insert a float not ending in .0 (such as 123.15) as the transactionTotalAmount. I tried to do it with 123.0 and it didn't work.

It should work with the following query:

mutation createCorrect {
  createTransaction(input: {name: "Lorem ipsum dolor sit amet",
          transactionDate: "2010-09-28",
          transactionTotalAmount: 123.15}) {
    name
    transactionDate
    transactionTotalAmount
    id
    createdAt
    updatedAt
  }
}

You should see your new index as the one below:
Pasted image 20220928182543

Notice how transactionDate is now parsed as a date and transactionTotalAmount as a float.

The following query should work as expected now:

query filterAndSort {
  searchTransactions(filter: {transactionTotalAmount: {eq: 123.15}},
  sort: {direction: desc, field: transactionDate}, limit: 10) {
    total
    items {
      id
      transactionDate
      createdAt
      transactionTotalAmount
    }
  }
}

Also you should be able to insert other values without the number being a float or the not ending in .0 restriction.

Persistent errors

If an AWSDate is present you can create a transaction with a transactionDate with a timezone such as explained in the AppSync documentation (e.g "1970-01-01Z" or "1970-01-01+05:30"). Whenever this happens a new transaction gets created but the searchTransactions query won't show it up in the results (the other transactions without timezones show up). You can still visualize them by listing all of the transactions with the listTransactions query.

A solution to this is using AWSDateTime or String instead of AWSDate.

Possible causes of the problem

I think it has to tho with the way Amazon OpenSearch Service parses the data. The index is created in the OpenSearch instance based on the first data registry that is inserted (I think this is the case as an index doesn't exist before the data is inserted). Also, according to the OpenSearch documentation, there is no timezone offset in the date data type in OpenSearch, so there might be conflicts when trying to get the transactionDate with a timezone.

@chrisbonifacio chrisbonifacio changed the title Using Search query on a float field returning expected results. Using Search query on a float field returning unexpected results. Oct 6, 2022
@chrisbonifacio chrisbonifacio added the bug Something isn't working label Oct 6, 2022
@iartemiev iartemiev transferred this issue from aws-amplify/amplify-js Oct 10, 2022
ncarvajalc added a commit to ncarvajalc/amplify-category-api that referenced this issue Oct 12, 2022
Float numbers ending in .0 where being parsed as integers in an
OpenSearch instance when using the @searchable directive. If this data
was the first being uploaded to the instance, searching queries wouldn't
work as expected. The change creates a JSON file which is uploaded with
the Python streaming function to lambda. The JSON has all the schema
data types of the @searchable model fields. A modified version of the
Python streaming function enables the DynamoDB event fields to be
correctly parsed to the correct data type described in the schema.

✅ Closes: aws-amplify#866
@ncarvajalc ncarvajalc linked a pull request Oct 12, 2022 that will close this issue
5 tasks
@AaronZyLee
Copy link
Contributor

Thanks for the details in issue report and contribution! The current behavior for the data type in elastic search is depending on the first inserted data following the dynamic mapping rules here. This is not ideal in some cases as you point out for float and date type with timezone. While the PR fixes the float type, we are currently working on a more generic solution for all the data type dynamic mapping. Still the PR really helps a lot for us to get a clear picture of this issue! I will update with the solution once the team approves the proposal.

@ncarvajalc
Copy link
Contributor

Thanks @AaronZyLee. Also, my solution can be extended to other data types as well, it just needs to add conditions in the Python lambda function to map to the correct type. I would be glad to contribute to this fix as I have time to work on it. I am currently working with the Amplify Team via the MLHFellowship this fall, so reach out to me if you need anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants