Determine total pages with Google list method - pagination

I'm working with the Google Blogger API and am finding its forcing pagination on me when retrieving a list of blog posts. It looks like several of the Google APIs offer a List method to return a list of [items]. The request has a maxResults parameter, which defaults to various numbers depending on the API (apparently 10 for Blogger).
The problem is I'm not seeing it returning the total number of posts or pages and my app has a progress bar to show the percentage of total posts that it has processed.
So I need to know how many posts there are total.
I found that the YouTube API's response for PlayListItems includes a pageInfo object with the total number of results in it.
Is there something like this that I'm just missing for Blogger Posts or do they really require paging without providing a way to get the total page count?

Posts: list returns a special type of response. It includes only the next page token and a list of the posts. The same is true for Pages.
{
"kind": "blogger#postList",
"nextPageToken": string,
"items": [
[posts Resource][2]
]
}
Most of the other google APIs will return totalResults, Which is the total number of rows that the request could return with out paging. Blogger doesn't do this as shown above. You can get around it in the following manner.
Blogs: get returns a blog Resource will return the information about the blog including the number of posts and pages it contains. This is the only way to my knowledge to get a full result of the number of rows.
"posts": {
"totalItems": 395,
"selfLink": "https://www.googleapis.com/blogger/v3/blogs/1969422610982987741/posts"
},
"pages": {
"totalItems": 1,
"selfLink": "https://www.googleapis.com/blogger/v3/blogs/1969422610982987741/pages"
},

Related

Shopware advanced pricing - update rule prices via API

so I got this issue that I have some rules set up for customer groups (each per different sales channel). I then used those rules in advanced pricing tab for some of my products. Now I would like to change the advanced product price for a single rule using API request. From what I understand, it should be possible using 'product-price' endpoint, PATCH method (https://shopware.stoplight.io/docs/admin-api/8fe455ace068a-list-with-basic-information-of-product-price-resources).
I am making a request with payload like below and url https://shop-domain/api/product-price/fda10622ed67472e82d800618b0c36d1:
advanced pricing img
amazon rule img
postman request img -204 No Content
product-price endpoint img
{
"data":
{
"type": "product_price",
"id": "fda10622ed67472e82d800618b0c36d1",
"attributes": {
"productId": "675b627cb3034444af9904bb41901a32",
"ruleId": "ace571bd8e6f48c88f17a551ed1e2654",
"price": [
{
"currencyId": "b7d2554b0ce847cd82f3ac9bd1c0dfca",
"net": 115.44,
"gross": 234.50,
"linked": false
}
],
"quantityStart": 1
}
}
}
... but I am getting no effect and no actual response (response is empty, 204 - No Content). What am I missing? The ultimate goal here for me is to be able to set up different prices for different sales channels like Amazon or eBay for given products. Also, the request I present here is for single update, though it would be better if this could be a bulk request (I've tried /api/_action/sync upserts as well, but I'm not sure how it should be done - documentation here seems to be quite laconic).
The "id" that I'm using here is product price id that I got using GET method on the same endpoint - for listing all product prices from advanced pricing (last image; /api/product-price: https://swagger.docs.fos.gg/).
What am I missing here, how it should be done properly? Should I use customer groups for rules or maybe Sales Channels (if it even makes any difference here)?

Can I expand the set of fields returned by the Google group members API?

I need to make a Google API call to get specific information about members of a group.
The API for fetching group members is described here: https://developers.google.com/admin-sdk/directory/v1/guides/manage-group-members
But this API only returns ONE of the fields that I require for each member. I also require first name, last name, display name, phone number, organization, job title, and department.
ALL the fields for a user are available through this API: https://developers.google.com/admin-sdk/directory/v1/guides/manage-users. But I don't want to make multiple API calls to get the user information that I need.
Is there a way to get a set of fields for the members of a group?
I have found an API parameter named "fields" which can REDUCE the number of fields returned by the "members" API: https://developers.google.com/admin-sdk/directory/v1/guides/performance#patch
But how do I INCREASE the number of fields returned?
Or, alternatively, can I make a call to the "users" API and FILTER on the group I am looking for?
I did an HTTP GET against https://admin.googleapis.com/admin/directory/v1/groups/groupKey/members.
It returned JSON in this format:
{
"kind": "directory#members",
"members": [
{"kind": "directory#member",
"id": "group member's unique ID",
"email": "liz#example.com",
"role": "MANAGER",
"type": "GROUP"
},
],
}
The "members" list does not include first name, last name, phone number, etc.
I expected an API parameter which I can use to specify which attributes to return in the "members" list.
By using a Google API batch request I was able to reduce the number of API calls to:
MEMBERS API request to get the members of a group.
BATCH API request comprised of 1000 USER API requests (due to the 1000 request limit per batch).
So, for example, a group with 2000 members takes 3 API calls in total:
Get the members of the group.
Get the attributes for the first 1000 users.
Get the attributes for the second 1000 users.
Here is the info for Google API batch requests:
https://developers.google.com/admin-sdk/directory/v1/guides/batch
And the Python Google library we are using provides a very clean wrapper:
https://googleapis.github.io/google-api-python-client/docs/batch.html

Why odata Trippinservice returns only 8 pages?

When I give the odata service url,https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People in browser,I only get 8 records.Why do I get only 8 records when there are total of 20 records in People entity?Is PageSize set in Trippinservice?Can anyone help me to understand this?
Yes, this service implements server-side paging.
Firstly we identify that server-side pagination is in effect from the presense of the #odata.nextLink property in the response, this is in the root of the response:
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"#odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24skiptoken=8",
"value": [
... 8 records ...
]
}
We can only assUme that the page size is 8 by counting the number of records in the response or by consulting the documentation for the given service. In this case there is a $skiptoken query parameter inside the next link, in this case it happens to have a value of 8 and this corresponds to the number of records, but only by coincidence.
NOTE: %24 is a dollar sign $ that has been url encoded
~/TripPinServiceRW/People?%24skiptoken=8
In the case of the TripPin service documented in the OData Basic Tutorial, the $skiptoken value represents the number of records to skip and is a common implementation, but it is not a standard.
There is no specific mention of the server page size for the People feed in the documentation, nor is there a standard way to document $skiptoken logic at all in the $metatdata. Have a read on how and why ASP.NET WebAPI implements skiptoken: Use $skiptoken for server-driven paging
We can demonstrate this by navigating the next nextLink or altering the $orderby:
GET: ~/TripPinServiceRW/People?$skiptoken=8
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"#odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24skiptoken=16",
"value": [
... 8 more records ...
]
}
The $skiptoken is now 16 in the new nextLink: ~/TripPinServiceRW/People?%24skiptoken=16. In many implementations the $skiptoken will represent the key value of the last record that was sent, but TripPin does not use this convention, we can verify that by changing the order:
Both of these responses will have $skiptoken=8 in the nextLink
GET: ~/TripPinServiceRW/People?$orderby=UserName
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"#odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24orderby=UserName&%24skiptoken=8",
"value": [
... 8 records ...
]
}
GET: ~/TripPinServiceRW/People?$orderby=UserName desc
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"#odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24orderby=UserName+desc&%24skiptoken=8",
"value": [
... 8 records ...
]
}
According to the specification, $skiptoken is an arbitrary token that services can use to retrieve the next page of data from a previously prepared set. The value of the $skiptoken will have special significance to the server itself and it may be an arbitrary token or reference pointing to a page in a cached resultset.
11.2.5.7 Server-Driven Paging
Responses that include only a partial set of the items identified by the request URL MUST contain a link that allows retrieving the next partial set of items. This link is called a next link; its representation is format-specific. The final partial set of items MUST NOT contain a next link.
OData clients MUST treat the URL of the next link as opaque, and MUST NOT append system query options to the URL of a next link. Services may not allow a change of format on requests for subsequent pages using the next link. Clients therefore SHOULD request the same format on subsequent page requests using a compatible Accept header. OData services may use the reserved system query option $skiptoken when building next links. Its content is opaque, service-specific, and must only follow the rules for URL query parts.
It is worth highlighting this very specific note in the specification:
OData clients MUST NOT use the system query option $skiptoken when constructing requests.
The $skiptoken is a server-side implementation and in many cases you couldn't even guess what a correct value might be. The TripPin service is a very simple demonstration API, it uses a page size of 8 to illustrate the behaviour of server-side paging, given the small size of the overall dataset (20) this is a nice arbitrary number that will result in multiple pages with the last page only partially full. That's enough to test basic compliance of server-side supporting data interfaces.
Server-side paging is designed to encourage search driven interfaces where users formulate more precise search criteria in preference to browsing through the pages 1 by 1. Virtual Scrolling is a common user interface paradigm that exploits server-side paging. Different languages and runtimes have different implementations but basically the user can scroll through a list or grid of data and when they get to the bottom there might be a link to "load more" records (behind the scenes, this will load the response from the nextLink). Sometimes this link is not displayed and the data is automatically loaded as the user approaches or reaches the end of the list.
You can still use traditional client-side paging using the $top and $skip query parameters, however some service implementations of server-side paging will still constrain the results to the fixed number of rows as defined by that servers internal logic. If you are implementing client-side paging then you may still need to use the nextLink to retrieve all the results for each client-side page of results.
Lets compare by first getting page 2, of a client-side page size of 5:
GET: ~/TripPinServiceRW/People?$skip=5&$top=5
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"value": [
... 5 records ...
]
}
Notice that there is no #odata.nextLink property in the response, that is because the requested number of items does not exceed the server page size logic. So lets try a page size of 9. This time, to retrieve all the records for the page, we will need to make multiple queries.
The general guidance here is to recursively call the service for each of the nextLink urls in the responses, if they contain a nextLink
GET: ~/TripPinServiceRW/People?$skip=9&$top=9
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"#odata.nextLink": "https://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/People?%24skip=9&%24top=9&%24skiptoken=8",
"value": [
... 8 records ...
]
}
GET: ~/TripPinServiceRW/People?%24skip=9&%24top=9&%24skiptoken=8
{
"#odata.context": "http://services.odata.org/V4/(S(ysqt4lcalbsipb1qkoc04ryb))/TripPinServiceRW/$metadata#People",
"value": [
... 1 record ...
]
}
When you are implementing your own OData-v4 conformant API it is important to understand this quirk and to document specifically in your API documentation what your policy or convention is with regard to server-side paging and which collections it is enabled on.
In my own implementations, I will often disable server-side paging if the request contains the client-paging token $top (and the value for $top is <= 200) but
From a client-side implementation if you see a nextLink property in the response and you didn't recieve the expected number of records, then you should query for the subsequent server-pages to fulfil your request if you are not able to implement a virtual Scroll enabled user experience.
NOTE: Normally when we discuss paging in OData v4 services the examples would include use of the $count query option.
[11.2.9 Requesting the Number of Items in a Collection]: On success, the response body MUST contain the exact count of items matching the request after applying any $filter or $search system query options...
The returned count MUST NOT be affected by $top, $skip, $orderby, or $expand.
The TripPin service DOES NOT CONFORM to this particular (and many other) clause in the specification, so I have not used that query option in this explanation.

Instagram not returning pagination object when searching photos by location

i'm trying to fetch links from the photos from certain area like this site does, but i'm not getting the next_url for the next page of photos, for example i use this:
https://api.instagram.com/v1/media/search?lat=20.881512&lng=-103.83429&distance=5000&access_token=ACCESS_TOKEN
but i don't get in the response this part:
{ "pagination":{
"next_url":"https#//api.instagram.com/v1/users/319505/media/recent?access_token=TOKEN&max_id=407185589491099817_319505",
"next_max_id":"407185589491099817_319505" }, "meta":{
"code":200 }, "data":["omitted"] }
and from the official site i couldn't find and example.
this is the json i get from the response:
http://www.jsoneditoronline.org/?id=6fef889a9037081244c7774edd73367b
i understand that some locations doesn't contain that many photos or no photos at all, but i tried with a very turistic place (like Paris,France) to avoid this sort of problem but no result.
This doesn't happen when i try a search with tags, any ideas? is this a bug?
Put &count=-1 at the and of your URL.
Like this: https://api.instagram.com/v1/users/(userID)/media/recent/?access_token=(accessToken)&count=-1

Search people with Google+ API

I have a several problem with Google+ API.
When I do a search, for example of my name: "Ismael" with the API
(you can do it with this URL): https://developers.google.com/+/api/latest/people/search
Google+ returns 50 results per page, and give a nextPageToken to see the next page. But when see 6 or 7 pages, always is the same token and I can't see more people.
In summary, I want to get for example 10000 or more results in a search, and I can just get less than 300. How can I achieve that?
Once there are no more results being returned and the nextPageToken matches the pageToken returned you can assume there are no more results. There just are not 10000 results for you to get.

Resources