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

[oData Handler] Count Not Behaving as Expected #944

Open
cpoliver opened this issue Sep 15, 2020 · 5 comments
Open

[oData Handler] Count Not Behaving as Expected #944

cpoliver opened this issue Sep 15, 2020 · 5 comments
Labels
bug Something isn't working

Comments

@cpoliver
Copy link

Following #864 I've got the latest version of the oData handler and GraphQL Mesh running and can confirm that both count and inlineCount are now valid QueryOptions.

However, using the count query option doesn't seem to do anything, and running the separate generated query with the same filter does not apply the filter. In fact, the filter appears to be ignored completely in the count query (TenanciesCount), because you can pass an invalid oData filter string and nothing happens, whereas you get an error if you pass it to the main (Tenancies) query.

Here is an example of my query:

query Demo {
	Tenancies(queryOptions:{
	  filter: "startswith(friendlyname, 'IAM')"
	  top: 3
	  count: true # the option is here but it does't seem to affect the returned object graph
	}) {
	  id
	  friendlyName
	  status
	}
	
    TenanciesCount(queryOptions:{
	  filter: "startswith(friendlyname, 'IAM')"
	})
}

Which returns:

{
  "data": {
    "Tenancies": [
      {
        "id": "3225f4b0-1fa0-ea11-9cd8-84fdd17eeb35",
        "friendlyName": "IAMCloud",
        "status": 1
      }
    ],

    "TenanciesCount": 4
  }
}

I'm not sure how I can get the count of the total number of filtered results, so I can handle pagination on the client side.

In the example above I'd TenanciesCount to be 1 in the example above, as there is 1 result for that given filter, and 4 results when the filter is not applied. Also, as an example, if there were 200 results when applying the filter, and I also requestion the top: 10 in the queryOptions, I'd still expect a count of 200 as this is the total amount of results, which is required to calculate the pagination.

I hope that contains enough information. Pinging @ardatan who was discussing this with me and asked me to raise an issue.

Thanks in advance!

@ardatan ardatan added the bug Something isn't working label Sep 15, 2020
@chrisweirich
Copy link

Same problem on my app using this handler. Are there any updates on this issue?

Regards
Chris

@ardatan
Copy link
Owner

ardatan commented Mar 28, 2022

Could you help us to reproduce it with our examples?

@chrisweirich
Copy link

chrisweirich commented Mar 28, 2022

@ardatan It is exactly as @cpoliver wrote.
The odata service returns an additional value "@odata.count" when adding "$count=true". But this value is discarded by the handler - probably because it is not in "value"?

Query

query users {
  Users(queryOptions: {filter: "contains(Name, 'Test Person')", count:true}) {
    ID
    Name
  }
}

Request
https://0.0.0.0:50000/v2/Users?$select=ID,Name&$filter=contains(Name, 'Test Person')&$count=true

Response odata service ("count" present)

{
	"@odata.count": "2",
	"@odata.context": "https://0.0.0.0:50000/v2/$metadata#Users",
	"value": [
		{
			"ID": 3,
			"Name": "Test Person 1"
		},
		{
			"ID": 4,
			"Name": "Test Person 2"
		}
	]
}

Response graphql mesh handler ("count" not present)

{
  "data": {
    "Users": [
      {
        "ID": "3",
        "Name": "Test Person 1"
      },
      {
        "ID": "4",
        "Name": "Test Person 2"
      }
    ]
  }
}

@chrisweirich
Copy link

chrisweirich commented Mar 28, 2022

Additionally, it seems that "$count" causes the other parameters (e.g. "$filter") to be discarded in some cases, and thus always returns the total count. I don't know if this is how it should be according to the odata protocol, but our SAP odata service does not discard them when called directly and returns the correct count.

Query

query {
  UsersCount(
    queryOptions: {filter: "contains(Name, 'Test Person')"}
  )
}

Response graphql mesh handler

{
  "data": {
    "UsersCount": 10923
  }
}

@chrisweirich
Copy link

Suggestion
https://github.com/Urigo/graphql-mesh/blob/master/packages/handlers/odata/src/index.ts#L1382

url.href = urljoin(url.href, `/${entitySetName}/$count`);
addIdentifierToUrl(url, identifierFieldName, identifierFieldTypeRef, args);
const parsedInfoFragment = parseResolveInfo(info) as ResolveTree;
const searchParams = this.prepareSearchParams(parsedInfoFragment, info.schema);
searchParams?.forEach((value, key) => {
  url.searchParams.set(key, value);
});
const urlString = getUrlString(url);

In my case the odata service always returns type String not type Int:
https://github.com/Urigo/graphql-mesh/blob/master/packages/handlers/odata/src/index.ts#L1375


type: 'String',

@theguild-bot theguild-bot mentioned this issue Aug 11, 2022
@theguild-bot theguild-bot mentioned this issue Sep 28, 2023
This was referenced Apr 30, 2024
This was referenced May 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants