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

Filters Doesn't Pass When There's Negative Numbers #13364

Closed
3 tasks done
fimbres opened this issue May 11, 2024 · 4 comments
Closed
3 tasks done

Filters Doesn't Pass When There's Negative Numbers #13364

fimbres opened this issue May 11, 2024 · 4 comments
Labels
GraphQL Related to GraphQL API issues question General question

Comments

@fimbres
Copy link

fimbres commented May 11, 2024

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

GraphQL API

Amplify Version

v6

Amplify Categories

api

Backend

Amplify CLI

Environment information

System:
    OS: macOS 14.4.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 1.60 GB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.17.1 - ~/.nvm/versions/node/v18.17.1/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 9.6.7 - ~/.nvm/versions/node/v18.17.1/bin/npm
    pnpm: 8.7.0 - /opt/homebrew/bin/pnpm
    bun: 1.0.23 - ~/.bun/bin/bun
  Browsers:
    Chrome: 124.0.6367.201
    Safari: 17.4.1
  npmPackages:
    @aws-amplify/react-native: ^1.0.28 => 1.0.28 
    @babel/core: ^7.20.0 => 7.24.4 
    @expo/vector-icons: ^14.0.0 => 14.0.0 
    @hookform/resolvers: ^3.3.4 => 3.3.4 
    @hookform/resolvers/ajv:  1.0.0 
    @hookform/resolvers/arktype:  1.0.0 
    @hookform/resolvers/class-validator:  1.0.0 
    @hookform/resolvers/computed-types:  1.0.0 
    @hookform/resolvers/io-ts:  1.0.0 
    @hookform/resolvers/joi:  1.0.0 
    @hookform/resolvers/nope:  1.0.0 
    @hookform/resolvers/superstruct:  1.0.0 
    @hookform/resolvers/typanion:  1.0.0 
    @hookform/resolvers/typebox:  1.0.0 
    @hookform/resolvers/valibot:  1.0.0 
    @hookform/resolvers/vest:  1.0.0 
    @hookform/resolvers/yup:  1.0.0 
    @hookform/resolvers/zod:  1.0.0 
    @react-native-async-storage/async-storage: 1.21.0 => 1.21.0 
    @react-native-community/datetimepicker: 7.6.1 => 7.6.1 
    @react-native-community/netinfo: 11.1.0 => 11.1.0 
    @react-native-picker/picker: 2.6.1 => 2.6.1 
    @react-navigation/native: ^6.0.2 => 6.1.17 
    @types/numeral: ^2.0.5 => 2.0.5 
    @types/react: ~18.2.45 => 18.2.79 
    HelloWorld:  0.0.1 
    aws-amplify: ^6.0.30 => 6.0.30 
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/data:  undefined ()
    aws-amplify/data/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    expo: ~50.0.14 => 50.0.17 
    expo-dev-client: ~3.3.11 => 3.3.11 
    expo-font: ~11.10.3 => 11.10.3 
    expo-image: ~1.10.6 => 1.10.6 
    expo-image-picker: ~14.7.1 => 14.7.1 
    expo-linear-gradient: ~12.7.2 => 12.7.2 
    expo-linking: ~6.2.2 => 6.2.2 
    expo-location: ~16.5.5 => 16.5.5 
    expo-router: ~3.4.8 => 3.4.8 
    expo-splash-screen: ~0.26.4 => 0.26.4 
    expo-status-bar: ~1.11.1 => 1.11.1 
    expo-system-ui: ~2.9.3 => 2.9.4 
    expo-web-browser: ~12.8.2 => 12.8.2 
    lucide-react-native: ^0.372.0 => 0.372.0 
    moment: ^2.30.1 => 2.30.1 
    numeral: ^2.0.6 => 2.0.6 
    react: 18.2.0 => 18.2.0 
    react-dom: 18.2.0 => 18.2.0 
    react-hook-form: ^7.51.3 => 7.51.3 
    react-native: 0.73.6 => 0.73.6 
    react-native-gesture-handler: ~2.14.1 => 2.14.1 
    react-native-get-random-values: ~1.8.0 => 1.8.0 
    react-native-google-places-autocomplete: ^2.5.6 => 2.5.6 
    react-native-mask-input: ^1.2.3 => 1.2.3 
    react-native-otp-entry: ^1.6.1 => 1.6.1 
    react-native-reanimated: ~3.6.2 => 3.6.3 
    react-native-reanimated-carousel: ^3.5.1 => 3.5.1 
    react-native-safe-area-context: 4.8.2 => 4.8.2 
    react-native-screens: ~3.29.0 => 3.29.0 
    react-native-svg: 14.1.0 => 14.1.0 
    react-native-svg-transformer: ^1.3.0 => 1.3.0 
    react-native-web: ~0.19.6 => 0.19.10 
    react-native-woodpicker: ^0.3.17 => 0.3.17 
    typescript: ^5.1.3 => 5.4.5 
    zod: ^3.23.4 => 3.23.4 
    zustand: ^4.5.2 => 4.5.2 
  npmGlobalPackages:
    corepack: 0.18.0
    npm: 9.6.7

Describe the bug

I'm trying to get all the records in my db filtering by lat and lng, I have a range for each field (lat, lng)

for lat it's all good because I don't have negative numbers. but for lng it's not passing.

In the following example you can see this is correct: -172.9272442976304 <= -116.604305 && -116.604305 <= -60.28136570236959. But for the amplify filters it's not correct.

This is my query statement:

const { data } = await client.graphql({
        query: listAffiliates,
        variables: {
          filter: {
            and: [
              {
                lat: {
                  between: [
                    minLat.toString(),
                    maxLat.toString(),
                  ]
                }
              },
              {
                lng: {
                  between: [
                    minLng.toString(),
                    maxLng.toString(),
                  ]
                }
              },
            ]
          }
        }
      });

it does not return any data when it should. Also if the minLng is bigger than the second one I get this error:

"data": {"listAffiliates": null}, "errors": [{"data": null, "errorInfo": null, "errorType": "DynamoDB:DynamoDbException", "locations": [Array], "message": "Invalid FilterExpression: The BETWEEN operator requires upper bound to be greater than or equal to lower bound; lower bound operand: AttributeValue: {S:-99}, upper bound operand: AttributeValue: {S:-172.9272442976304} (Service: DynamoDb, Status Code: 400, Request ID: GM23LH500RQJS300U71GAKBUNFVV4KQNSO5AEMVJF66Q9ASUAAJG)", "path": [Array]}]}

for example: -90 and -120 triggers the error, but -120, and -90 doesn't. It's kinda like if the values are parsed to positive to make the comparison or something like that. Because -90 is bigger than -120.

So I'm just wondering if there's any solution for this, in order to filter using negative values as lat, lng.

Expected behavior

Filter the records in my db in order to get the nearest to the user.

Reproduction steps

  1. initialize a new amplify project.
  2. create a model with a Int field.
  3. create a record for this model and enter a negative number in this numeric field
  4. try to filter this record by its numeric field using a couple negative values.
  5. face the error.

Code Snippet

// Put your code below this line.
const { data } = await client.graphql({
        query: listAffiliates,
        variables: {
          filter: {
            and: [
              {
                lat: {
                  between: [
                    minLat.toString(),
                    maxLat.toString(),
                  ]
                }
              },
              {
                lng: {
                  between: [
                    minLng.toString(),
                    maxLng.toString(),
                  ]
                }
              },
            ]
          }
        }
      });
GraphQL model
type Affiliate @model @searchable {
  id: ID!
  name: String!
  lat: String!
  lng: String!
}

Log output

// Put your logs below this line


aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

Iphone 15 pro Simulator

Mobile Operating System

IOS 17.4

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

@fimbres fimbres added the pending-triage Issue is pending triage label May 11, 2024
@ChristopherGabba
Copy link

ChristopherGabba commented May 13, 2024

@fimbres

I think it's because you defined Lat and Long as a String in your schema.

You need to use Float or Int for the filter to be able to work.

GraphQL model
type Affiliate @model @searchable {
  id: ID!
  name: String!
  lat: Float!
  lng: Float!
}

@fimbres
Copy link
Author

fimbres commented May 13, 2024

Hey @ChristopherGabba lol you were right. I thought it was already a Float.
But now after migrating it seems that any Float comparison is not returning data at all. I did the migration and in my db all Affiliate's records have lat & lng of type number. But even if I do something like this:

lat: {
    eq: 31.8754079,
},

it's not returning any data. using eq with the name field (String) works tho. any idea on this one?

@ChristopherGabba
Copy link

ChristopherGabba commented May 13, 2024

Disclaimer, I'm some random struggling with DynamoDB as well.

Without seeing your data, and knowing what's in there, the filter line just filters the first set of results after they have been fetched. I've struggled a lot here, but I think you may need to set up secondaryIndex queries for your data with sortKeys, instead of using the filter expression.

For example, lets say I just use a basic list query like you have used to find all people with the first name John.

If I have 500 users registered, and I set my query limit to 100, it's going to read through the first 100 people in the database and completely ignore the next 400 unless I provide a nextToken. That's called a scan query in dynamoDB vs. a query operation, and its basically worthless for most applications. I honestly don't know why they even structure that option. Instead you assign the firstName as a secondaryIndex and it actually queries all your data for people with a first name as John.

That being said, using your filter expressions like you did above is going to get the first say 100 affiliates in your database and then filter them by your data, because you are using the scan method. Also using the eq flag is only going to get fields with that exact number. As an experiment to test your query, make the limit on your query above to like 1000000000 and see if you get results, but don't use this in production because it will be expensive. You need to set up secondaryIndexes.

@chrisbonifacio chrisbonifacio added GraphQL Related to GraphQL API issues question General question labels May 13, 2024
@chrisbonifacio
Copy link
Contributor

I'm going to close this issue as the original issue has been solved thanks to @ChristopherGabba, but I would recommend opening a new one regarding the issue of no data being returned to track it separately as a potential bug and with details for the team to reproduce

@chrisbonifacio chrisbonifacio removed the pending-triage Issue is pending triage label May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GraphQL Related to GraphQL API issues question General question
Projects
None yet
Development

No branches or pull requests

3 participants