Developer forum

Forum » Ecommerce - Standard features » Keep sortorder from request

Keep sortorder from request

Anders Ebdrup
Reply

Hello,

 

Is it possible to keep the sort order from the request e.g. when requesting related products? So if I have a related product list with these MainProductId: 0562127PPF,0662125PPF,0562125PPF,0162120PPF,0562126PPF, I would expect to have the products returned in the same order as the request, because I have no sorting order set on the query.

 

Best regards, Anders


Replies

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply
This post has been marked as an answer

The query is a query - passed to Lucene and Lucene will always sort - if nothing specified, it will use Score - which is probably the same numeric value, but a sorting algorithm will do what it does.

To keep the order of the search result it can be done when rendering the result, you need to do that in the template.

Or maybe a notification subscriber - AI says this:

using System;
using System.Collections.Generic;
using System.Linq;
using Dynamicweb;
using Dynamicweb.Core;
using Dynamicweb.Extensibility.Notifications;
using Dynamicweb.Indexing;
using QueryNotifications = Dynamicweb.Indexing.Notifications.Query;

namespace Dynamicweb.Ecommerce.Products.NotificationSubscribers;

/// <summary>
/// Re-sorts query results to match the order of the MainProductId query string parameter.
/// </summary>
[Subscribe(QueryNotifications.AfterQuery)]
public sealed class MainProductIdQuerySortSubscriber : NotificationSubscriber
{
    /// <summary>
    /// Runs late so other subscribers can finish first.
    /// </summary>
    public override int Rank => 1000;

    /// <summary>
    /// Handles the AfterQuery notification.
    /// </summary>
    /// <param name="notification">The notification name.</param>
    /// <param name="args">The notification arguments.</param>
    public override void OnNotify(string notification, NotificationArgs args)
    {
        if (!string.Equals(notification, QueryNotifications.AfterQuery, StringComparison.OrdinalIgnoreCase))
            return;

        if (args is not QueryNotifications.AfterQueryArgs afterQueryArgs || afterQueryArgs.Result is null)
            return;

        string? mainProductIdsValue = Context.Current?.Request?["MainProductId"];
        if (string.IsNullOrWhiteSpace(mainProductIdsValue))
            return;

        var requestedIds = mainProductIdsValue
            .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);

        if (requestedIds.Length == 0)
            return;

        var documents = afterQueryArgs.Result.QueryResult.ToList();
        if (documents.Count == 0 || documents.Count != requestedIds.Length)
            return;

        var positions = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
        for (int i = 0; i < requestedIds.Length; i++)
        {
            if (!positions.TryAdd(requestedIds[i], i))
                return;
        }

        var sortedDocuments = new object[documents.Count];

        foreach (var document in documents)
        {
            if (document is not IndexDocument indexDocument)
                return;

            if (!TryGetDocumentMainProductId(indexDocument, out string documentMainProductId))
                return;

            if (!positions.TryGetValue(documentMainProductId, out int position))
                return;

            sortedDocuments[position] = indexDocument;
        }

        if (sortedDocuments.Any(document => document is null))
            return;

        afterQueryArgs.Result.QueryResult = sortedDocuments;
        afterQueryArgs.Result.Count = sortedDocuments.Length;
    }

    private static bool TryGetDocumentMainProductId(IndexDocument document, out string mainProductId)
    {
        if (TryGetStringValue(document, "ProductNumber", out mainProductId))
            return true;

        if (TryGetStringValue(document, "ID", out mainProductId))
            return true;

        mainProductId = string.Empty;
        return false;
    }

    private static bool TryGetStringValue(IndexDocument document, string fieldName, out string value)
    {
        if (document.TryGetValue(fieldName, out object? rawValue))
        {
            value = Converter.ToString(rawValue);
            if (!string.IsNullOrWhiteSpace(value))
                return true;
        }

        value = string.Empty;
        return false;
    }
}
Votes for this answer: 1

 

You must be logged in to post in the forum