SWR: How to efficiently handle filtering? - swr

Let's say that we are displaying books grouped by author. The GET request would look as follows:
// The server parses this like: author=['tolkien', 'shakespeare']
const data = useSWR('example.com/books?author[]=tolkien&author[]=shakespeare')
After having fetched this, the user now also wants to see the books written by another author. The easy thing to do here would be to fire off the following request:
const data = useSWR('example.com/books?author[]=tolkien&author[]=shakespeare&author[]=rowling')
Here data includes all the books by Tolkien, Shakespeare and Rowling.
But we already have the books by Tolkien and Shakespeare, so fetching these again would be a waste. Instead it would make more sense to call the following:
const data = useSWR('example.com/books?author[]=rowling')
But here the books by Tolkien and Shakespeare are not included in data.
Is it possible to call the following:
const data = useSWR('example.com/books?author[]=tolkien&author[]=shakespeare&author[]=rowling')
Where only the books by Rowling are actually fetched and are added to the 'example.com/books?author[]=tolkien&author[]=shakespeare&author[]=rowling' key?
Similarly, let's say that we want to show only the books by Tolkien:
const data = useSWR('example.com/books?author[]=tolkien')
But calling the above would refetch Tolkien's books, even though we already have them...
What is the correct way to handle this scenario with SWR?

Related

Magento 2 REST API understanding fields

Can someone explain the "status" and "visibility" fields on each product in the list obtained through Magento 2 REST API?
When calling the /products endpoint a list of products are returned but I'm having issues understanding the different fields. Sure, some fields are self explanatory like sku, name, etc. but others like status and visibility aren't.
Looking at the documentation, I can see both values are integers but no further explanation as to what values are allowed and what they actually mean? That makes the documentation kinda useless since I can probably just guess the type looking at the often related GET-request.
Documentation found here:
https://magento.redoc.ly/2.4.1-admin/tag/products#operation/catalogProductRepositoryV1GetListGet
I have no former experience with Magento :D
Maybe there is a reference list somewhere that explains each field?
Hope someone can help me!
If you have a look at four constants at the top of the class Visibility: https://github.com/magento/magento2/blob/2.4-develop/app/code/Magento/Catalog/Model/Product/Visibility.php
const VISIBILITY_NOT_VISIBLE = 1;
const VISIBILITY_IN_CATALOG = 2;
const VISIBILITY_IN_SEARCH = 3;
const VISIBILITY_BOTH = 4;
you will see what values are allowed and what they mean: IN_CATALOG means that the product will not be taken into account when user is using search, while IN_SEARCH means that the product will not show on product page and category page, but will be returned in search results, the other two (NOT_VISIBLE, BOTH) are a combination of these two both being false or both being true.
Now about status - have a look here: https://github.com/magento/magento2/blob/2.4-develop/app/code/Magento/Catalog/Model/Product/Attribute/Source/Status.php
Again, you have constants which are used to store the status:
/**
* Product Status values
*/
const STATUS_ENABLED = 1;
const STATUS_DISABLED = 2;
I hope this answers your question :)

How to attach multiple parameters to an API request?

I built my own simple REST API with Express and now I'm consuming it from my client (Vue.js)
So in my page I access all the data from this endpoint: GET /api/books, and it works fine
Now I also have a "sort by" button where I want to get the data by the latest entries. I don't know if that's a good way or if I have to handle this in the backend but what I do is calling the same endpoint which is GET /api/books and sorting the data to get them the right way
For ex:
sortByLatest() {
axios
.get("/api/books")
.then(res => {
const books = res.data;
const sortedBooks = books.sort((a, b) => b.createdAt > a.createdAt ? 1 : -1
);
this.books = sortedBooks;
})
// catch block
}
I do that for everything. If I need a limited number of results or a specific property from the data I have to write some logic in the axios .then block to sort or filter what I want. Is this bad practice?
But that's not my actual problem
My problem is, in addition of sorting by the latest entries, I also want to filter the results by a specific property. The problem is when I click the A button it's gonna filter the books by a specific property, and when I click the B button it's gonna sort them buy the latest entries, but not both at the same time!
And what if I want additionnal things like limit the number of results to 10, filter by other properties etc... I want to be able to create requests that ask all those things at once. How can I do that? Do I have to build that in the backend?
I saw some websites using url parameters to filter stuff, like /genre=horror&sort=latest, is that the key of doing it?
Thank you for your time

Wix Corvid database connection with online Store Products and Collections

Lets say I need to have some logic in this use case scenario. The user is on the WIX Online Store's Product page for a particular product and clicks on QTY to order more units of the product. The logic to add is to check against the inventory at that moment and send a Twilio SMS message to the Store owner as a warning(this use case is somewhat contrived).
The thing is I dont seem to see any examples on WIX online training that shows how the Corvid Database can be connected to existing WIX Online stores which have Products and Collections already defined (which I assume is kept in some database). How does the Corvid Database and the Online Store Products/Collections map and how is it done and how can Corvid js code access that ? By the way, the Corvid uses the term "Collections" which does not seem related to Product Collections which must be a source of confusion for many.
You can access your Wix-Stores products collection using the wix-data module.
import wixStoresBackend from 'wix-stores-backend'; // Not needed here but try in the editor
import wixData from 'wix-data';
const WIX_STORES_PRODUCT_TABLE = 'Stores/Products';
const getProducts = () => {
return wixData.query(WIX_STORES_PRODUCT_TABLE)
.find()
.then((data) => {
let wixInventory = data.items;
return wixInventory
}
If you start there you will see all the items in your Wix-Stores. You can further query the database/collection by narrowing down the query. There are some good starter examples in the Corvid documentation for query here.
Just as a note - Because the Wix-Stores collections are read only you can query them but you can't write to them. If you have a look at wixStoresBackend within the Corvid editor the code completion there shows that you can update some parameters of a product however, you will need to modify a product's item if you want to adjust things like quantity.

RESTful API - How do I return different results for the same resource?

Question
How do I return different results for the same resource?
Details
I have been searching for some time now about the proper way to build a RESTful API. Tons of great information out there. Now I am actually trying to apply this to my website and have run into a few snags. I found a few suggestions that said to base the resources on your database as a starting point, considering your database should be structured decently. Here is my scenario:
My Site:
Here is a little information about my website and the purpose of the API
We are creating a site that allows people to play games. The API is supposed to allow other developers to build their own games and use our backend to collect user information and store it.
Scenario 1:
We have a players database that stores all player data. A developer needs to select this data based on either a user_id (person who owns the player data) or a game_id (the game that collected the data).
Resource
http://site.com/api/players
Issue:
If the developer calls my resource using GET they will receive a list of players. Since there are multiple developers using this system they must specify some ID by which to select all the players. This is where I find a problem. I want the developer to be able to specify two kinds of ID's. They can select all players by user_id or by game_id.
How do you handle this?
Do I need two separate resources?
Lets say you have a controller name 'Players', then you'll have 2 methods:
function user_get(){
//get id from request and do something
}
function game_get(){
//get id from request and do something
}
now the url will look like: http://site.com/api/players/user/333, http://site.com/api/players/game/333
player is the controller.
user/game are the action
If you use phil sturgeon's framework, you'll do that but the url will look like:
http://site.com/api/players/user/id/333, http://site.com/api/players/game/id/333
and then you get the id using : $this->get('id');
You can limit the results by specifying querystring parameters, i.e:
http://site.com/api/players?id=123
http://site.com/api/players?name=Paolo
use phil's REST Server library: https://github.com/philsturgeon/codeigniter-restserver
I use this library in a product environment using oauth, and api key generation. You would create a api controller, and define methods for each of the requests you want. In my case i created an entirely seperate codeigniter instance and just wrote my models as i needed them.
You can also use this REST library to insert data, its all in his documentation..
Here is a video Phil threw together on the basics back in 2011..
http://philsturgeon.co.uk/blog/2011/03/video-set-up-a-rest-api-with-codeigniter
It should go noted, that RESTful URLs mean using plural/singular wording e.g; player = singular, players = all or more than one, games|game etc..
this will allow you to do things like this in your controller
//users method_get is the http req type.. you could use post, or put as well.
public function players_get(){
//query db for players, pass back data
}
Your API Request URL would be something like:
http://api.example.com/players/format/[csv|json|xml|html|php]
this would return a json object of all the users based on your query in your model.
OR
public function player_get($id = false, $game = false){
//if $game_id isset, search by game_id
//query db for a specific player, pass back data
}
Your API Request URL would be something like:
http://api.example.com/player/game/1/format/[csv|json|xml|html|php]
OR
public function playerGames_get($id){
//query db for a specific players games based on $userid
}
Your API Request URL would be something like:
http://api.example.com/playerGames/1/format/[csv|json|xml|html|php]

NHibernate AliasToBeanResultTransformer & Collections

I would like to return a DTO from my data layer which would also contain child collections...such as this:
Audio
- Title
- Description
- Filename
- Tags
- TagName
- Comments
- PersonName
- CommentText
Here is a basic query so far, but i'm not sure how to transform the child collections from my entity to the DTO.
var query = Session.CreateCriteria<Audio>("audio")
.SetProjection(
Projections.ProjectionList()
.Add(Projections.Property<Audio>(x => x.Title))
.Add(Projections.Property<Audio>(x => x.Description))
.Add(Projections.Property<Audio>(x => x.Filename))
).SetResultTransformer(new AliasToBeanResultTransformer(typeof(AudioDto)))
.List<AudioDto>();
Is this even possible, or is there another reccomended way of doing this?
UPDATE:
Just want to add a little more information about my scenario...I want to return a list of Audio items to the currently logged in user along with some associated entities such as tags, comments etc...these are fairly straight forward using MultiQuery / Future.
However, when displaying the audio items to the user, i also want to display 3 other options to the user:
Weather they have added this audio item to their list of favourites
Weather they have given this audio the 'thumbs up'
Weather the logged in user is 'Following' the owner of this audio
Favourites : Audio -> HasMany -> AudioUserFavourites
Thumbs Up : Audio -> HasManyToMany -> UserAccount
Following Owner : Audio -> References -> UserAccount ->
ManyToMany -> UserAccount
Hope this makes sense...if not i'll try and explain again...how can I eager load these extra details for each Audio entity returned...I need all this information in pages of 20 also.
I looked at Batch fetching, but this appears to fetch ALL thumbs ups for each Audio entity, rather than checking if only the logged in user has thumbed it.
Sorry for rambling :-)
Paul
If you want to fetch your Audio objects with both the Tags collection and Comments collections populated, have a look at Aydende Rahien's blog: http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate.
You don't need to use DTOs for this; you can get back a list of Audio with its collections even if the collections are lazily loaded by default. You would create two future queries; the first will fetch Audio joined to Tags, and the second will fetch Audio joined to Comments. It works because by the time the second query result is being processed, the session cache already has the Audio objects in it; NHibernate grabs the Audio from the cache instead of rehydrating it, and then fills in the second collection.
You don't need to use future queries for this; it still works if you just execute the two queries sequentially, but using futures will result in just one round trip to the database, making it faster.