Add custom sortation to catalog/lists with ElasticSearch

Help for integrating the Laravel package
Forum rules
Always add your Laravel, Aimeos and PHP version as well as your environment (Linux/Mac/Win)
Spam and unrelated posts will be removed immediately!
kdim95
Advanced
Posts: 211
Joined: 26 Aug 2022, 12:17

Add custom sortation to catalog/lists with ElasticSearch

Post by kdim95 » 12 Jun 2023, 22:18

Laravel framework version: 10.12.0
Aimeos Laravel version: ~2023.04
PHP Version: 8.2.6
Environment: Linux

Hello,

How can I add custom sort to catalog/lists with es-elastic?

I have added a custom attribute to my products with a decorator:

Code: Select all

<?php

namespace Aimeos\MShop\Product\Manager\Decorator;

class MyDecorator
	extends \Aimeos\MShop\Common\Manager\Decorator\Base
	implements \Aimeos\MShop\Common\Manager\Decorator\Iface
{
	private $attr = [
		'orders' => [
			'code' => 'orders',
			'internalcode' => 'mpro."orders"',
			'label' => 'Number of times this product has been ordered',
			'type' => 'integer',
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_INT,
		],
	];
	
	public function getSaveAttributes() : array
    {
        return parent::getSaveAttributes() + $this->createAttributes( $this->attr );
    }
	
	public function getSearchAttributes( bool $sub = true ) : array
    {
        return parent::getSearchAttributes( $sub ) + $this->createAttributes( $this->attr );
    }
}
This is part of the code, which counts how many times a certain product has been ordered.
The attribute is already added as a column to the products table.

I am using this parameter on the product listing page: f_sort=-orders

I have also added this to Aimeos\Controller\Frontend\Product\StandardCustom:

Code: Select all

public function sort( string $key = null ) : Iface
{
	...
	
	foreach( $list as $sortkey )
	{
		...

		switch( $sortkey )
		{
			...

			case 'orders':
				$this->addExpression( $this->filter->sort( $direction, 'orders' ) );
				break;

			...
		}
	}
}
I get this error:

Code: Select all

/shop?f_sort=-orders
Invalid name "orders"
#0 /var/www/vhosts/***********/httpdocs/vendor/aimeoscom/ai-elastic/src/Base/Criteria/Elastic.php(163): Aimeos\Base\Criteria\Expression\Sort\Elastic->toSource()

User avatar
aimeos
Administrator
Posts: 7941
Joined: 01 Jan 1970, 00:00

Re: Add custom sortation to catalog/lists with ElasticSearch

Post by aimeos » 14 Jun 2023, 07:56

Did you configure your decorator for the product manager?
Do you use Elastic as primary product store or only for fast index?
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

kdim95
Advanced
Posts: 211
Joined: 26 Aug 2022, 12:17

Re: Add custom sortation to catalog/lists with ElasticSearch

Post by kdim95 » 14 Jun 2023, 08:09

aimeos wrote: 14 Jun 2023, 07:56 Did you configure your decorator for the product manager?
Do you use Elastic as primary product store or only for fast index?
This is my Elastic configuration in "shop.php"

Code: Select all

'index' => [
			'manager' => [
				'name' => 'ElasticIndex',
				'attribute' => [
					'name' => 'Elastic',
				],
				'catalog' => [
					'name' => 'Elastic',
				],
				'price' => [
					'name' => 'Elastic',
				],
				'supplier' => [
					'name' => 'Elastic',
				],
				'text' => [
					'name' => 'Elastic',
				],
			],
		],
This is my config for the product manager decorator, it should be active, because it outputs the values when dumping a product item:

config/mshop/product.php

Code: Select all

<?php

return [
    'manager' => [
        'name' => 'StandardCustom',
        'decorators' => [
            'local' => [ 'MyDecorator' ]
        ],
    ]
];

User avatar
aimeos
Administrator
Posts: 7941
Joined: 01 Jan 1970, 00:00

Re: Add custom sortation to catalog/lists with ElasticSearch

Post by aimeos » 14 Jun 2023, 08:22

Yes, but only for the product manager. When the (Elastic) index manager is used by the frontend controller, it doesn't know of any additional search keys available in the product manager. You have to add your decorator to the index manager too.
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

kdim95
Advanced
Posts: 211
Joined: 26 Aug 2022, 12:17

Re: Add custom sortation to catalog/lists with ElasticSearch

Post by kdim95 » 14 Jun 2023, 11:43

I think I understand what you're talking about.

Testing by removing the key product.ratings from Aimeos\MShop\Product\Manager\Elastic yields the same error.
But it seems logical to me that my existing decorator in my-extension/config/mshop/product.php should be loaded.

Why is the decorator not visible when working with the Elastic product manager?

Code: Select all

return [
    'manager' => [
        'name' => 'StandardCustom',
        'decorators' => [
            'local' => [ 'MyDecorator' ]
        ],
    ]
];

kdim95
Advanced
Posts: 211
Joined: 26 Aug 2022, 12:17

Re: Add custom sortation to catalog/lists with ElasticSearch

Post by kdim95 » 14 Jun 2023, 13:22

Further testing:

I added this to Aimeos\MShop\Product\Manager\Elastic:

Code: Select all

$searchConfig = [
    ...

    'orders' => array(
        'code' => 'orders',
        'internalcode' => 'base.product.orders',
        'label' => 'Number of orders',
        'type' => 'integer',
        'internaltype' => 'integer',
        'public' => false,
    ),

    ...
]
The "Invalid name" error stopped showing up, but now it's not filtering by the number of orders.

I'm sure that there is at least one queried product, which has an order count of 1 in the aimeos index.
The other products are set to 0

What should I do to get this working?

kdim95
Advanced
Posts: 211
Joined: 26 Aug 2022, 12:17

Re: Add custom sortation to catalog/lists with ElasticSearch

Post by kdim95 » 15 Jun 2023, 00:35

I somewhat got the sorting working, but still have questions.

What is the proper way to override Aimeos\MShop\Product\Manager\Elastic?

I need to add orders in the $searchConfig, but don't want to modify the original class.

It looks like when mshop/index/manager/name = ElasticIndex is set, then you can't set mshop/product/manager/name. I want to set it to ElasticCustom and create a custom Elastic class, where I will extend the original and add the "orders" attribute, overriding the getSearchAttributes() method.

Aimeos\MShop\Product\Manager\Elastic $searchConfig:

Code: Select all

'orders' => array(
	'code' => 'orders',
	'internalcode' => 'base.orders',
	'label' => 'Number of times this product has been ordered',
	'type' => 'integer',
	'internaltype' => 'integer',
	'public' => false,
),
I left the decorator Aimeos\MShop\Product\Manager\Decorator\MyDecorator like this.
Otherwise the orders attribute I want to use does not get indexed in ElasticSearch.

Code: Select all

<?php

namespace Aimeos\MShop\Product\Manager\Decorator;

class MyDecorator
	extends \Aimeos\MShop\Common\Manager\Decorator\Base
	implements \Aimeos\MShop\Common\Manager\Decorator\Iface
{
	private $attr = [
		'orders' => [
			'code' => 'orders',
			'internalcode' => 'mpro."orders"',
			'label' => 'Number of times this product has been ordered',
			'type' => 'integer',
			'internaltype' => \Aimeos\Base\DB\Statement\Base::PARAM_INT,
		],
	];
	
	public function getSaveAttributes() : array
    {
        return parent::getSaveAttributes() + $this->createAttributes( $this->attr );
    }
	
	public function getSearchAttributes( bool $sub = true ) : array
    {
        return parent::getSearchAttributes( $sub ) + $this->createAttributes( $this->attr );
    }
}

The Elastic class is extended in Aimeos\MShop\Product\Manager\ElasticIndex.

I was planning to create an ElasticIndexCustom class, specify that as the name in mshop/index/manager/name = ElasticIndexCustom, then instead of the extended Elastic inside ElasticIndexCustom, extend another custom ElasticCustom class, where I would add my custom $searchConfig, but that solution seems too messy and I will have to override a bunch of the ai-elastic core code when extending the classes.

The end goal is to add a custom sort attribute to products, also to override as little code as possible so its easier to update in the future.

User avatar
aimeos
Administrator
Posts: 7941
Joined: 01 Jan 1970, 00:00

Re: Add custom sortation to catalog/lists with ElasticSearch

Post by aimeos » 16 Jun 2023, 07:50

You should be able to create a decorator similar to your existing one (only the "internalcode" value is different for Elastic) and apply it to the index manager in the ./config/mshop/index.php:

Code: Select all

return [
    'manager' => [
        'decorators' => [
            'local' => [ 'MyDecorator' ]
        ],
    ]
];
Index manager decorator:

Code: Select all

<?php

namespace Aimeos\MShop\Index\Manager\Decorator;

class MyDecorator
	extends \Aimeos\MShop\Common\Manager\Decorator\Base
	implements \Aimeos\MShop\Common\Manager\Decorator\Iface
{
	private $attr = [
		'orders' => [
			'code' => 'orders',
			'internalcode' => 'base.product.orders"',
			'label' => 'Number of times this product has been ordered',
			'type' => 'integer',
			'internaltype' => 'integer',
		],
	];
	
	public function getSaveAttributes() : array
	{
		return parent::getSaveAttributes() + $this->createAttributes( $this->attr );
	}

	public function getSearchAttributes( bool $sub = true ) : array
	{
		return parent::getSearchAttributes( $sub ) + $this->createAttributes( $this->attr );
	}
}
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

kdim95
Advanced
Posts: 211
Joined: 26 Aug 2022, 12:17

Re: Add custom sortation to catalog/lists with ElasticSearch

Post by kdim95 » 19 Jun 2023, 13:54

Thank you, that seems to work.

But when using the ElasticIndex, this config doesn't seem to work:

/mshop/product/manager/name

What is the proper way to override the product manager and add a custom overriden product item class?

The goal is add custom methods to the item class to get and set attributes.

I tried adding this to my decorator, reading from this documentation:

https://aimeos.org/docs/2023.x/models/extend-managers/

Code: Select all

\Aimeos\MShop\Product\Item\Standard::method( 'getMycolumn', function() {
    return (int) $this->get( 'mycolumn' );
} );
I get the following error:

syntax error, unexpected fully qualified name "\Aimeos\MShop\Product\Item\Sta...", expecting "function" or "const"

I have no issues like this when not using the ElasticSearch index.

User avatar
aimeos
Administrator
Posts: 7941
Joined: 01 Jan 1970, 00:00

Re: Add custom sortation to catalog/lists with ElasticSearch

Post by aimeos » 20 Jun 2023, 06:35

kdim95 wrote: 19 Jun 2023, 13:54 But when using the ElasticIndex, this config doesn't seem to work:
/mshop/product/manager/name
Can you please post you complete (custom) configuration related to the mshop config key?
kdim95 wrote: 19 Jun 2023, 13:54

Code: Select all

\Aimeos\MShop\Product\Item\Standard::method( 'getMycolumn', function() {
    return (int) $this->get( 'mycolumn' );
} );
syntax error, unexpected fully qualified name "\Aimeos\MShop\Product\Item\Sta...", expecting "function" or "const"
You need to add that to your app/Providers/AppServiceProvider.php in the boot() method.
Professional support and custom implementation are available at Aimeos.com
If you like Aimeos, Image give us a star

Post Reply