Secondary sorting in Magento - sql

I have come across a problem which my developer says there is no solution to.
I have an ecommerce site www.lovefashion.pk roughly 800 products to date. It has categories with collections of products from a particular brand and New Arrivals and Sale pages that show a number of categories. The issue I am faced with is the way Magento displays these products on catalog pages.
We create a custom sort 'BY date' and called it 'Latest' so I would choose a date for a collection and the catalog pages would show the collection with newest sort by date first and so on. Issue is with secondary sorting now. I have products with design codes say Brand A code 1-A, Brand A code 1-B, Brand A code 2-A and so on. When creating these products, we go alphabetically like 1-A,1-B, 2-A etc.
Say a collection has 15 products and i have given all its products a sort by date of 15th April. Magento does the date sorting OK but secondary sorting i.e by product ID (oldest to newest) is what we cant find a way to implement. It shows products now with latest ID first, i.e 20-B, 20-A, 19-B, and so on till 1-A e.g http://www.lovefashion.pk/shop-by-price/
Is there a way to solve this problem? or can SQL manipulation do the trick? Will aprreicate any help

This is a very interesting question. Can you tell us a little more about what you are trying to do? I think you want the products on each page reversed, but the pages to keep the order they have, yes? or do you want the page to go 'Asim Jofa Luxury Lawn Collection 2014 / 1-A' then 'Orient Lawn Kurti Collection 2014 / 01-B' then 'Orient Lawn Kurti Collection 2014 / 01-A' and so on?
Anyway, I think all you need to do is code a secondary sorting of the collection for each page which could be coded in the list.phtml file.
Psuedo code:
get the collection sorted by date and paginated
reverse the collection
pass the collection into the existing foreach(){echo(<li>product info</li>)}
So 'reverse the collection' might be tricky. And strictly you want to sort by sku on 1A, 1B, 2A, 2B - but I'm sure your developer can figure it out.
$reversed_collection = array_reverse($current_page_collection->toArray());
might work but I think the toArray will loose all the class types so it's not the same as reversing the object.
Collections are like arrays so end($current_page_collection) and prev($current_page_collection) might work but you would have to try it (and report back if it works). In that case a simple for loop to iterate over each item of the colection.
If you are making a custom filter then really it is just a case of putting each item of the collection into an array with an appropriate key and sorting with ksort().
So it is my opinion that it can be sorted that way, but it should be done in two stages.

Related

Elastic Search, Nest. functional sorting

I'm building a filter page, with facets etc, which works as it should.
Now the our customer has a request to, basically "Be able to decide which sorting the items comes out in".
Each product is decorated with a Product Display Order, and is in a Product Line.
We got these example Product Display Orders:
1. Featured Item
2. Core Item
3. Spare Part
4. Utility
And these Product Lines:
1. Hammers
2. Saw
3. Wood
and the sorting is like this:
Sorting should firstly be based on Product Display Orders, secondly by product lines, thirdly Alphabetically.
So all products which is a Featured Item is listed first, and all these Featured Items is then sorted by their product line, and if some product are in the same Featured Item and Product Line, then its alphabetically.
The challenge is: I can't just get the sorting of Product Display order items and product lines as a number on the product, i only got a name/id.
We've thought of Boosting based on if the product are in the different categories, but it seems a bit messy.
OR
See if it possible to have some logic in the Sorting.
Sort by productDisplayOrder:
1. featured, 2. core Item ...
Then by ProductLines:
1. Hammers, 2. Saw ...
Then by Name DESC.
Which way is the best way to have this sorting, is it possible to give this logic to elastic, if it is a match and then sort it. Or are we needed to twist the boosts of product?
Hopefully this makes sense for you.
Thanks in advance! :)
Option 1). Quickest/Best performing solution would be to create new/separate integer fields for productDisplayOrder and ProductLine and then use those in your sort criteria as described (after reindexing and validating the the data is indexed as expected).
Option 2) If you want more nuance than described (eg higher scoring matches can 'break through' the ordering ceiling described) then you can explore using a Function Score Query to implement a custom scoring strategy that takes productDisplayOrder and ProductLine into consideration in generating an overall match score.
Option 3). If you can't change the mapping and reindexing your data, you can use Script-Based Sorting to generate sorting values from the currently indexed productDisplayOrder/ProductLine text using a script (eg Groovy). Keep in mind that query performance will be worse than the first two options.

Shopify : Is it possible to Sort Collection by date product is UPDATED rather than CREATED

is it possible to sort a collection by the date a product has been updated rather than the original creation date?
For instance if a product sells out, but then I add some new stock later, i'd like it to reappear at the top of the sorted list, rather than always being tied to the original creation date.
Can this be done using any sort of custom script?

How to keep a list of 'used' data per user

I'm currently working on a project in MongoDB where I want to get a random sampling of new products from the DB. But my problem is not MongoDB specific, I think it's a general database question.
The scenario:
Let's say we have a collection (or table) of products. And we also have a collection (or table) of users. Every time a user logs in, they are presented with 10 products. These products are selected randomly from the collection/table. Easy enough, but the catch is that every time the user logs in, they must be presented with 10 products that they have NEVER SEEN BEFORE. The two obvious ways that I can think of solving this problem are:
Every user begins with their own private list of all products. Each time they get one of these products, the product is removed from their private list. The result is that the next time products are chosen from this previously trimmed list, it already contains only new items.
Every user has a private list of previously viewed products. When a user logs in, they select 10 random products from the master list, compare the id of each against their list of previously viewed products, and if the item appears on the previously viewed list, the application throws this one away selects a new one, and iterates until there are 10 new items, which it then adds to the previously viewed list for next time.
The problem with #1 is it seems like a tremendous waste. You would basically be duplicating the list data for n number of users. Also removing/adding new items to the system would be a nightmare since it would have to iterate through all users. #2 seems preferable, but it too has issues. You could end up making a lot of extra and unnecessary calls to the DB in order to guarantee 10 new products. As a user goes through more and more products, there are less new ones to choose from, so the chances of having to throw one away and get new one from the DB greatly increases.
Is there an alternative solution? My first and primary concern is performance. I will give up disk space in order to optimize performance.
Those 2 ways are a complete waste of both primary and secondary memory.
You want to show 2 never before seen products, but is this a real must?
If you have a lot of products 10 random ones have a high chance of being unique.
3 . You could list 10 random products, even though not as easy as in MySQL, still less complicated than 1 and 2.
If you don't care how random the sequence of id's is you could do this:
Create a single randomized table of just product id's and a sequential integer surrogate key column. Start each customer at a random point in the list on first login and cycle through the list ordered by that key. If you reach the end, start again from the top.
The customer record would contain a single value for the last product they saw (the surrogate from the randomized list, not the actual id). You'd then pull the next ten on login and do a single update to the customer. It wouldn't really be random, of course. But this kind of table-seed strategy is how a lot of simpler pseudo-random number generators work.
The only problem I see is if your product list grows more quickly than your users log in. Then they'd never see the portions of the list which appear before wherever they started. Even so, with a large list of products and very active users this should scale much better than storing everything they've seen. So if it doesn't matter that products appear in a set psuedo-random sequence, this might be a good fit for you.
Edit:
If you stored the first record they started with as well, you could still generate the list of all things seen. It would be everything between that value and last viewed.
How about doing this: crate a collection prodUser where you will have just the id of the product and the list of customersID, (who have seen these products) .
{
prodID : 1,
userID : []
}
when a customer logs in you find the 10 prodID which has not been assigned to that user
db.prodUser.find({
userID : {
$nin : [yourUser]
}
})
(For some reason $not is not working :-(. I do not have time to figure out why. If you will - plz let me know.). After showing the person his products - you can update his prodUser collection. To mitigate mongos inability to find random elements - you can insert elements randomly and just find first 10.
Everything should work really fast.

MS Access tables that need to be in the listbox

OK, I have the worst VB class in the world. The friggin textbook has you do programming projects but the stupid book doesn't even explain everything required for the project. Oh yeah, the professor for the class doesn't help worth a crap (online schooling).
So needless to say, I have been struggling with the class for a very VERY LONG TIME...
Well, here's my request:
Here is visual representation of what is required
Now, I have been fighting this thing for MANY MANY hours and would like some tips and advice on how to get this stupid thing done. I usually get more specific when it comes to posting in this website except this time, it seems like I have a problem with EVERYTHING!!!
Here is the instructions:
"The database Microland.accdb is maintained by the Microland Computer Warehouse, a mail-order computer-supply company. The tables below show data in the three tables in the database. The table Customers identifies each customer by an ID number and gives, in addition to the name and address, the total amount of purchases during the current year prior to today. The table Inventory identifies each product in stock by an ID number and gives, in addition to its description and price (per unit), the quantity in stock at the beginning of the day. The table Orders gives the orders received today. Assume that it is now the end of the day. Write a Visual Basic program that uses the three tables to do the following two tasks:
Display in a listbox the items that are out of stock and those that must be reordered to satisfy today’s orders.
Display in a listbox bills for all customers who ordered during the day. Each bill should show the customer’s name, address, items ordered (with costs), and total cost of the order.
So, if any of you VB geniuses would like to tell me how to do some of this stuff, that would be absolutely awesome. Any kind of help will definitely make a difference for me.
(I'm assuming it's VB.NET) Here's some pointers on the bigger picture, you'll need Google to fill-in the details:
1) Establish a connection to your Access database using ADO.NET. Maybe do this in code or use the data tools in Visual Studio?
2) Write a query (in Access or plain SQL) to find the count of the distinct stock items that have been purchased today and subtract that from the count of the items in stock at the beginning of the day. Select the items where the count is zero or less.
You can use the visual builder in Access and save the query object, referring to this query object in code. Or you can copy the SQL generated by Access and use this with ADO.NET command objects.
3) Show the results of this query in a listbox. Either step through the DataReader adding items to listbox in code, or investigate databinding to your datasource.
4) Write another query that shows the data requested in step 2 in your question and then list those results in another listbox.
Try to get a little further with it and then respond with progress and further issues.

Need Help Writing SQL To Apply Promotions to Shopping Basket at Checkout

Don't laugh but I'm a Lotus Notes (non-relational database!) developer trying to work with SQL and, although I have the basic concepts nailed, I'm stuck on something I'd consider to be "advanced".
Imagine a user reaches an online checkout having added a set of products to their basket. I need to apply promotions to the basket.
These promotions look at the items in the basket and add "points" for any combination that matches a pre-defined "bundle". The promotions also need to be able to target users in specific countries (information gained at point of registration) and other personal details.
The promotions are entered and maintained by the site admin team and need to be as flexible as possible. So they can reward people for things like "Buy X products of type Y and get 50% extra points" or "3 or more XE-123s and get 500 points added" etc.
Right now I'm looking for general direction. How should I store the criteria that matches the items in a basket to any of the running promotions? Would one big Stored Procedure do or should the C# code that builds the basket loop through all promotions and see which fit?
Right now I don't even have a table schema. Just the knowledge of how it should work and little idea where to start.
Jake
My suggestion is to not use SQL for this sort of business logic.
The database is a good place to keep information about products like whether they are type Y or type X. This keeps the database design pretty straightforward.
What you mention about C# seems like a better direction. There is a lot of searchable information about 3-tier architecture that can help explain the benefits of this strategy well.
'As flexible as possible' is a red flag (IMHO). I'd try to nail that down to:
"Fixed-point and/or percentage (of total basket / bundle points) bonus (three columns in a helper table)
When the basket contains a combination that matches a pre-defined 'bundle', where 'bundle' is contained in a helper table, with multiply rows, with a bundleID and a row for each item in the bundle, containing at least ItemID and Quantity.
And no other kinds of reward possible. This to keep the project / requirement manageable.
Then have a SP which checks for the presence of bundles within the basket and applies relevant promotions (as stored in the first helper table).
Also make sure you know the requirement whether 1 or multiple promotions are possible.