Show only product with special prices - pagination

Is it possible to show only products with special prices?
I put {% if product.special %} in my product_card.twig, and that works fine but then my pagination doesn't work correctly. It still shows the total number of products that belongs to that category.
I have 5 products in some category but pagination says "Showing 1 to 9 of 9 (1 pages)".
Is there any other way to achieve this?

You should create new model function that get query from DB some thing like
public function getSpecialByCategory() {
// your query here
}
and get result by controller then controller send it to your Twig file.

Related

TYPO3: Performance issue with pagination

I am currently building some kind of video channel based on an extension I created. It consists of videos and playlist that contains videos (obviously).
I have to create a page which contains a list of videos AND playlist by category. You also can sort those items by date. Finally, the page is paginated with an infinite scrolling that should load items 21 by 21.
To do so, I created on both Video and Playlist repositories a "findByCategory" function which is really simple :
$query = $this->createQuery();
return $query->matching($query->equals('categorie.uid',$categoryUid))->execute()->toArray();
Once I requested the items I need, I merge them in one array and do my sorting stuff. Here is my controller show action :
if ($this->request->hasArgument('sort'))
$sort = $this->request->getArgument('sort');
else
$sort = 'antechrono';
//Get videos in repositories
$videos = $this->videoRepository->findByCategorie($categorie->getUid());
$playlists = $this->playlistRepository->findByCategorie($categorie->getUid());
//Merging arrays then sort it
if ($videos && $playlists)
$result = array_merge($videos, $playlists);
else if ($videos)
$result = $videos;
else if ($playlists)
$result = $playlists;
if ($sort == "chrono")
usort($result, array($this, "sortChrono"));
else if ($sort == "antechrono" || $sort == null)
{
usort($result, array($this, "sortAnteChrono"));
$sort="antechrono";
}
$this->view->assignMultiple(array('categorie' => $categorie, 'list' => $result, 'sort' => $sort));
Here is my view :
<f:widget.paginate objects="{list}" as="paginatedList" configuration="{addQueryString: 'true', addQueryStringMethod: 'GET,POST', itemsPerPage: 21}">
<div class="videos row">
<f:for each="{paginatedList}" as="element">
<f:render partial="Show/ItemCat" arguments="{item: element}"/>
</f:for>
</div>
</f:widget.paginate>
The partial render shows stuff including a picture used as a cover. So I need at least this relation in the view.
This works fine and shows only the items from the category that is requested. Unfortunatly I have a huge performance issue : I tried to show a category that contains more than 3000 records and It takes about one minute to load. It's a little bit long.
By f:debugging my list variable, I see that it contains every records even through it shouldn't be the case (that's the point of pagination...). So the first question is : is there something wrong in the way I did my pagination ?
I tried to simplify my requests by enabling the rawQuery thing ($query->execute(true)) : I get way better performance, but I can't get the link for the pictures (in my view, I get 1 or 0 but not the picture's uid...). Second question : is there a way to fix this issue ?
I hope my description is clear enough. Thanks for your help :-)
When you execute a query, it will not actually fetch the data from the database until the results are accessed. If the paginate widget gets a query result it will add limits and offset to the query and then fetch the data from the database, so you will only get the records that are shown on a page.
In your case you added toArray() after execute(), which accesses the results, so the data is fetched from the database and you get all records. The best solution I can think of is to combine the 2 tables into 1 so you can do it with a single query and don't have to merge and order them in PHP.
As long as you sort the data after the query you have to handle all data (request all records and especially resolve all relations).
Try to sort the data in the query itself (order by), so you could restrict the data to only those records which are needed for the current 'page' (limit <offset>,<number>).
Here a complex query with join and limit could be faster than a full query and filtering in PHP.

Suitescript Pagination

Ive been trying to create a suitelet that allows for a saved search to be run on a collection of item records in netsuite using suitescript 1.0
Pagination is quite easy everywhere else, but i cant get my head around how to do it in NetSuite.
For instance, we have 3,000 items and I'm trying to limit the results to 100 per page.
I'm struggling to understand how to apply a start row and a max row parameter as a filter so i can run the search to return the number of records from my search
I've seen plenty of scripts that allow you to exceed the limit of 1,000 records, but im trying to throttle the amount shown on screen. but im at a loss to figure out how to do this.
Any tips greatly appreciated
function searchItems(request,response)
{
var start = request.getParameter('start');
var max = request.getParameter('max');
if(!start)
{
start = 1;
}
if(!max)
{
max = 100;
}
var filters = [];
filters.push(new nlobjSearchFilter('category',null,'is',currentDeptID));
var productList = nlapiSearchRecord('item','customsearch_product_search',filters);
if(productList)
{
response.write('stuff here for the items');
}
}
You can approach this a couple different ways. Either way, you will definitely need to sort your search results by something meaningful and consistent, like by internal ID. Make sure you've got your results sorted either in your saved search definition or by adding a search column in your script.
You can continue building your search exactly like you are, and then just using the native slice method on the productList Array. You would use your start and end parameters to pass as the arguments to slice appropriately.
Another approach is to use the async API for searches. It will look similar to this:
var search = nlapiLoadSearch("item", "customsearch_product_search");
search.addFilter(new nlobjSearchFilter('category',null,'is',currentDeptID));
var productList = search.runSearch().getResults(start, end);
For more references on this approach, check out the NetSuite Help page titled "Search APIs" and the reference page for nlobjSearch.

loopback relational database hasManyThrough pivot table

I seem to be stuck on a classic ORM issue and don't know really how to handle it, so at this point any help is welcome.
Is there a way to get the pivot table on a hasManyThrough query? Better yet, apply some filter or sort to it. A typical example
Table products
id,title
Table categories
id,title
table products_categories
productsId, categoriesId, orderBy, main
So, in the above scenario, say you want to get all categories of product X that are (main = true) or you want to sort the the product categories by orderBy.
What happens now is a first SELECT on products to get the product data, a second SELECT on products_categories to get the categoriesId and a final SELECT on categories to get the actual categories. Ideally, filters and sort should be applied to the 2nd SELECT like
SELECT `id`,`productsId`,`categoriesId`,`orderBy`,`main` FROM `products_categories` WHERE `productsId` IN (180) WHERE main = 1 ORDER BY `orderBy` DESC
Another typical example would be wanting to order the product images based on the order the user wants them to
so you would have a products_images table
id,image,productsID,orderBy
and you would want to
SELECT from products_images WHERE productsId In (180) ORDER BY orderBy ASC
Is that even possible?
EDIT : Here is the relationship needed for an intermediate table to get what I need based on my schema.
Products.hasMany(Images,
{
as: "Images",
"foreignKey": "productsId",
"through": ProductsImagesItems,
scope: function (inst, filter) {
return {active: 1};
}
});
Thing is the scope function is giving me access to the final result and not to the intermediate table.
I am not sure to fully understand your problem(s), but for sure you need to move away from the table concept and express your problem in terms of Models and Relations.
The way I see it, you have two models Product(properties: title) and Category (properties: main).
Then, you can have relations between the two, potentially
Product belongsTo Category
Category hasMany Product
This means a product will belong to a single category, while a category may contain many products. There are other relations available
Then, using the generated REST API, you can filter GET requests to get items in function of their properties (like main in your case), or use custom GET requests (automatically generated when you add relations) to get for instance all products belonging to a specific category.
Does this helps ?
Based on what you have here I'd probably recommend using the scope option when defining the relationship. The LoopBack docs show a very similar example of the "product - category" scenario:
Product.hasMany(Category, {
as: 'categories',
scope: function(instance, filter) {
return { type: instance.type };
}
});
In the example above, instance is a category that is being matched, and each product would have a new categories property that would contain the matching Category entities for that Product. Note that this does not follow your exact data scheme, so you may need to play around with it. Also, I think your API query would have to specify that you want the categories related data loaded (those are not included by default):
/api/Products/13?filter{"include":["categories"]}
I suggest you define a custom / remote method in Product.js that does the work for you.
Product.getCategories(_productId){
// if you are taking product title as param instead of _productId,
// you will first need to find product ID
// then execute a find query on products_categories with
// 1. where filter to get only main categoris and productId = _productId
// 2. include filter to include product and category objects
// 3. orderBy filter to sort items based on orderBy column
// now you will get an array of products_categories.
// Each item / object in the array will have nested objects of Product and Category.
}

ServiceStack route definition for a parameter that is an array

I have a service that will return top N items in sales given a bunch of different criteria. So if I have a GET route, how do I set the route to handle an array of a certain parameter?
Top 100 items for group A,C,D,E,F for the current week.
Top 100 items for store 1,10,11,18,40 for the current month.
How could the route be structured to handle this?
Its already wired up for you. For the groups example the route declaration will look like this:
Items/{Groups}
The Items DTO will need this property
public string[] Groups { get; set; }
Then you can just call it like so /Items/A,C,D,E,F
The array will get populated correctly.

Unable to order Haystack/Whoosh results (and it's extremely slow)

I'm using Haystack and Whoosh to search a custom app with city data from the Geonames project.
I only have a small amount of the Geonames city data imported (22917 records). I'd like to order the results by a city's population and I'm having trouble getting good results.
When I use order_by on my SearchQuerySet, the results are extremely slow. It also orders properly with against the 'name' field but not 'population', so I think I'm probably just doing something wrong.
Here's the search index:
class EntryIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
name = indexes.CharField(indexed=False, model_attr='ascii_name')
population = indexes.CharField(indexed=False, model_attr='population')
django_id = indexes.CharField(indexed=False, model_attr='id')
def get_model(self):
return Entry
def index_queryset(self):
return self.get_model().objects.all()
Here's the template:
{{ object.ascii_name }}
{{ object.alternate_names }}
{{ object.country.name }}
{{ object.country.iso }}
{{ object.admin1_division.ascii_name }}
{{ object.admin1_division.name }}
{{ object.admin1_division.code }}
{{ object.admin2_division.ascii_name }}
{{ object.admin2_division.name }}
Here's the relevant view code:
query = request.GET.get('q', '')
results = SearchQuerySet().models(Entry).auto_query(query).order_by('population')
When I take the order_by off the query, it returns in less than one second. With it on, it takes almost 10 seconds to complete, and the results are not ordered by population. Ordering by name works, but it also takes ~10 seconds.
Note: I've also tried with the built-in Haystack search view, and it's very slow when I try to order by population:
qs = SearchQuerySet().order_by('-population')
urlpatterns = patterns('',
...
url(r'^demo2/$', SearchView(searchqueryset=qs)),
)
I'm doing nearly the same thing, and ordering works fast and correctly for me.
The only thing you're doing that differs significantly is:
query = request.GET.get('q', '')
results = SearchQuerySet().models(Entry).auto_query(query).order_by('population')
Since you specify a request, I'm assuming you've created your own view. You shouldn't need a custom view. I have this implemented with this in my urls.py:
from haystack.forms import ModelSearchForm
from haystack.query import SearchQuerySet
from haystack.views import SearchView, search_view_factory
sqs = SearchQuerySet().models(MyModel).order_by('-weight')
urlpatterns += patterns('',
url(r'^search/$', search_view_factory(
view_class=SearchView,
template='search/search.html',
searchqueryset=sqs,
form_class=ModelSearchForm
), name='search'),
)
I found I could not order results using order_by either. I was getting what seemed like a strange partial sorting. I eventually realised that the default ordering was by relevance ranking. The order_by I was using was presumably only sorting within each rank. This point is not really brought out in the Haystack documentation.
I guess the lesson is probably that if you want your results order to ignore relevance you need to post process your results before displaying them.
Probably a bit off topic, but I was a little surprised your index population field is a CharField. Does this match with your model?
I know I'm three years late, but recently I faced the same issue with a project I've been given.
I guess the only problem is the indexed=False parameter you are passing to the population CharField.
I fixed my problem by removing that.

Resources