Posted on 01/10/2025 10:28:27
I do not understand what you want.
But I asked Chatgpt for an example of what you are trying to do - can you confirm? And now you have pointers... :-).
****************
Here’s a simple toy data example (in relational / tabular form) of groups and products illustrating that idea. Use this as a model for how you might store sorts in your index or DB.
Entities & fields
Let me define a few tables / structures:
Groups
| GroupID |
ParentGroupID |
SortOrder |
Name |
| G1 |
null |
10 |
“Electronics” |
| G1.1 |
G1 |
20 |
“Mobile Phones” |
| G1.2 |
G1 |
30 |
“Tablets” |
| G2 |
null |
40 |
“Home & Kitchen” |
| G2.1 |
G2 |
50 |
“Appliances” |
Products
| ProductID |
Name |
(Leaf) GroupID |
ProductSortOrder |
UniversalSortKey |
| P1 |
“iPhone 15” |
G1.1 |
5 |
— |
| P2 |
“Galaxy S24” |
G1.1 |
2 |
— |
| P3 |
“iPad Pro” |
G1.2 |
1 |
— |
| P4 |
“Blender X2000” |
G2.1 |
3 |
— |
| P5 |
“Toaster 3000” |
G2.1 |
1 |
— |
Compute universal sort key (concatenation approach)
The suggestion is: take the sort value of the top group, of the subgroup (leaf), and of the product itself, combine them into a composite key (e.g. as string or numeric concatenation), so that when you list across groups you have a consistent sort.
Let’s compute:
So we fill in the UniversalSortKey column:
| ProductID |
Name |
GroupID |
ProdSort |
UniversalSortKey |
| P1 |
iPhone 15 |
G1.1 |
5 |
10 |
| P2 |
Galaxy S24 |
G1.1 |
2 |
10 |
| P3 |
iPad Pro |
G1.2 |
1 |
10 |
| P4 |
Blender X2000 |
G2.1 |
3 |
40 |
| P5 |
Toaster 3000 |
G2.1 |
1 |
40 |
If you sort by UniversalSortKey (lexicographically or numerically, depending on how you encode), you get:
-
10|20|02 → P2 (Galaxy S24)
-
10|20|05 → P1 (iPhone 15)
-
10|30|01 → P3 (iPad Pro)
-
40|50|01 → P5 (Toaster 3000)
-
40|50|03 → P4 (Blender X2000)
So the ordering interleaves across categories in a deterministic way based on group priorities.
Notes & caveats (because I’m me, and I question things)
-
If a product belongs to multiple groups, which group do you use to derive the chain? Use the “primary” or “lowest sort value” group, or pick based on some rule.
-
You might need to pad sort order numbers (e.g. make them fixed width: 05, 10, etc.) so that concatenation sorts properly as strings.
-
If your hierarchy levels are inconsistent (some groups depth = 2, others = 3), you need a normalization strategy (fill missing levels with zeros, or default values).
-
Performance: computing this for large catalogs dynamically might be expensive; better to compute ahead and store in the index. (That matches what Nuno warns about) doc.dynamicweb.com
I also asked GPT to give me some code:
***********
Dynamicweb already dumps the group sort orders into fields like Sort_GROUP5, Sort_GROUP89, etc. in the index document, along with GroupIDs, ParentGroupIDs, and GroupsTop. That means the data is available in the index pipeline — we just need to stitch it together.
Here’s a working extender example that computes a UniversalSortKey field:
using System;
using System.Linq;
using System.Text;
using Dynamicweb.Ecommerce.Indexing;
namespace Dynamicweb.Indexing.Examples
{
public class ProductSortKeyExtender : IIndexBuilderExtender<ProductIndexBuilder>
{
public void ExtendDocument(IndexDocument indexDocument)
{
// GroupIDs is usually a string[] (e.g. "GROUP5 GROUP89 ...")
var groupIds = indexDocument.ContainsKey("GroupIDs")
? indexDocument["GroupIDs"] as string[]
: null;
if (groupIds == null || groupIds.Length == 0)
return;
// Just take the first group for the primary sort (you could implement your own "primary group" logic here)
var primaryGroupId = groupIds.First();
// Try to find the group's sort order field (e.g. Sort_GROUP5)
int groupSort = 0;
var sortFieldKey = $"Sort_{primaryGroupId}";
if (indexDocument.ContainsKey(sortFieldKey) && indexDocument[sortFieldKey] is int)
{
groupSort = (int)indexDocument[sortFieldKey];
}
// Product sort order (stored as Sort_GROUPX per group, so we fallback to groupSort or 0 if missing)
// If you have a product-level sort field independent of groups, swap this in
int productSort = groupSort;
// Optionally: also bring in top-level group order if available
int topGroupSort = 0;
var topGroups = indexDocument.ContainsKey("GroupsTop")
? indexDocument["GroupsTop"] as string[]
: null;
if (topGroups != null && topGroups.Any())
{
var topGroupId = topGroups.First();
var topSortFieldKey = $"Sort_{topGroupId}";
if (indexDocument.ContainsKey(topSortFieldKey) && indexDocument[topSortFieldKey] is int)
{
topGroupSort = (int)indexDocument[topSortFieldKey];
}
}
// Build the universal sort key, padded for lexicographic sorting
string universalSortKey = $"{topGroupSort:D3}|{groupSort:D3}|{productSort:D3}";
// Add it to the document
if (!indexDocument.ContainsKey("UniversalSortKey"))
{
indexDocument.Add("UniversalSortKey", universalSortKey);
}
else
{
indexDocument["UniversalSortKey"] = universalSortKey;
}
}
}
}
How it works
-
Finds the group IDs from the GroupIDs array.
-
Pulls the group sort order from the corresponding Sort_GROUPxxx fields.
-
Optionally includes top group sort order (from GroupsTop if available).
-
Builds a padded key like 010|020|005 so lexicographic sorting works.
-
Writes it into the index as UniversalSortKey.
Example result
For a product in GROUP5 (sort=20), under top group GROUP1 (sort=10), with product sort=5, the extender will add:
UniversalSortKey = "010|020|005"
You can now sort on this field across products consistently in queries.
Hope this helps.