Skip to content

feat(recommend): Add trending types and methods #1396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Mar 14, 2022
Merged
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
},
{
"path": "packages/recommend/dist/recommend.umd.js",
"maxSize": "4.1KB"
"maxSize": "4.2KB"
}
]
}
46 changes: 46 additions & 0 deletions packages/recommend/src/__tests__/getTrendingFacets.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { TestSuite } from '../../../client-common/src/__tests__/TestSuite';

const recommend = new TestSuite('recommend').recommend;

function createMockedClient() {
const client = recommend('appId', 'apiKey');
jest.spyOn(client.transporter, 'read').mockImplementation(() => Promise.resolve());

return client;
}

describe('getTrendingFacets', () => {
test('builds the request', async () => {
const client = createMockedClient();

await client.getTrendingFacets(
[
{
indexName: 'products',
facetName: 'company',
},
],
{}
);

expect(client.transporter.read).toHaveBeenCalledTimes(1);
expect(client.transporter.read).toHaveBeenCalledWith(
{
cacheable: true,
data: {
requests: [
{
indexName: 'products',
model: 'trending-facets',
facetName: 'company',
threshold: 0,
},
],
},
method: 'POST',
path: '1/indexes/*/recommendations',
},
{}
);
});
});
44 changes: 44 additions & 0 deletions packages/recommend/src/__tests__/getTrendingItems.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { TestSuite } from '../../../client-common/src/__tests__/TestSuite';

const recommend = new TestSuite('recommend').recommend;

function createMockedClient() {
const client = recommend('appId', 'apiKey');
jest.spyOn(client.transporter, 'read').mockImplementation(() => Promise.resolve());

return client;
}

describe('getTrendingItems', () => {
test('builds the request', async () => {
const client = createMockedClient();

await client.getTrendingItems(
[
{
indexName: 'products',
},
],
{}
);

expect(client.transporter.read).toHaveBeenCalledTimes(1);
expect(client.transporter.read).toHaveBeenCalledWith(
{
cacheable: true,
data: {
requests: [
{
indexName: 'products',
model: 'trending-items',
threshold: 0,
},
],
},
method: 'POST',
path: '1/indexes/*/recommendations',
},
{}
);
});
});
10 changes: 9 additions & 1 deletion packages/recommend/src/builds/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import { createBrowserXhrRequester } from '@algolia/requester-browser-xhr';
import { createUserAgent } from '@algolia/transporter';

import { createRecommendClient } from '../createRecommendClient';
import { getFrequentlyBoughtTogether, getRecommendations, getRelatedProducts } from '../methods';
import {
getFrequentlyBoughtTogether,
getRecommendations,
getRelatedProducts,
getTrendingFacets,
getTrendingItems,
} from '../methods';
import { BaseRecommendClient, RecommendOptions, WithRecommendMethods } from '../types';

export default function recommend(
Expand Down Expand Up @@ -47,6 +53,8 @@ export default function recommend(
getFrequentlyBoughtTogether,
getRecommendations,
getRelatedProducts,
getTrendingFacets,
getTrendingItems,
},
});
}
Expand Down
10 changes: 9 additions & 1 deletion packages/recommend/src/builds/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import { createNodeHttpRequester } from '@algolia/requester-node-http';
import { createUserAgent } from '@algolia/transporter';

import { createRecommendClient } from '../createRecommendClient';
import { getFrequentlyBoughtTogether, getRecommendations, getRelatedProducts } from '../methods';
import {
getFrequentlyBoughtTogether,
getRecommendations,
getRelatedProducts,
getTrendingFacets,
getTrendingItems,
} from '../methods';
import { BaseRecommendClient, RecommendOptions, WithRecommendMethods } from '../types';

export default function recommend(
Expand Down Expand Up @@ -41,6 +47,8 @@ export default function recommend(
getFrequentlyBoughtTogether,
getRecommendations,
getRelatedProducts,
getTrendingFacets,
getTrendingItems,
},
});
}
Expand Down
11 changes: 8 additions & 3 deletions packages/recommend/src/methods/getRecommendations.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { MethodEnum } from '@algolia/requester-common';

import { BaseRecommendClient, RecommendationsQuery, WithRecommendMethods } from '../types';
import {
BaseRecommendClient,
RecommendationsQuery,
TrendingQuery,
WithRecommendMethods,
} from '../types';

type GetRecommendations = (
base: BaseRecommendClient
) => WithRecommendMethods<BaseRecommendClient>['getRecommendations'];

export const getRecommendations: GetRecommendations = base => {
return (queries: readonly RecommendationsQuery[], requestOptions) => {
const requests: readonly RecommendationsQuery[] = queries.map(query => ({
return (queries: ReadonlyArray<RecommendationsQuery | TrendingQuery>, requestOptions) => {
const requests: ReadonlyArray<RecommendationsQuery | TrendingQuery> = queries.map(query => ({
...query,
// The `threshold` param is required by the endpoint to make it easier
// to provide a default value later, so we default it in the client
Expand Down
32 changes: 32 additions & 0 deletions packages/recommend/src/methods/getTrendingFacets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { MethodEnum } from '@algolia/requester-common';

import { BaseRecommendClient, TrendingFacetsQuery, WithRecommendMethods } from '../types';

type GetTrendingFacets = (
base: BaseRecommendClient
) => WithRecommendMethods<BaseRecommendClient>['getTrendingFacets'];

export const getTrendingFacets: GetTrendingFacets = base => {
return (queries: readonly TrendingFacetsQuery[], requestOptions) => {
const requests: readonly TrendingFacetsQuery[] = queries.map(query => ({
...query,
model: 'trending-facets',
// The `threshold` param is required by the endpoint to make it easier
// to provide a default value later, so we default it in the client
// so that users don't have to provide a value.
threshold: query.threshold || 0,
}));

return base.transporter.read(
{
method: MethodEnum.Post,
path: '1/indexes/*/recommendations',
data: {
requests,
},
cacheable: true,
},
requestOptions
);
};
};
32 changes: 32 additions & 0 deletions packages/recommend/src/methods/getTrendingItems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { MethodEnum } from '@algolia/requester-common';

import { BaseRecommendClient, TrendingItemsQuery, WithRecommendMethods } from '../types';

type GetTrendingItems = (
base: BaseRecommendClient
) => WithRecommendMethods<BaseRecommendClient>['getTrendingItems'];

export const getTrendingItems: GetTrendingItems = base => {
return (queries: readonly TrendingItemsQuery[], requestOptions) => {
const requests: readonly TrendingItemsQuery[] = queries.map(query => ({
...query,
model: 'trending-items',
// The `threshold` param is required by the endpoint to make it easier
// to provide a default value later, so we default it in the client
// so that users don't have to provide a value.
threshold: query.threshold || 0,
}));

return base.transporter.read(
{
method: MethodEnum.Post,
path: '1/indexes/*/recommendations',
data: {
requests,
},
cacheable: true,
},
requestOptions
);
};
};
2 changes: 2 additions & 0 deletions packages/recommend/src/methods/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
export * from './getFrequentlyBoughtTogether';
export * from './getRecommendations';
export * from './getRelatedProducts';
export * from './getTrendingFacets';
export * from './getTrendingItems';
3 changes: 2 additions & 1 deletion packages/recommend/src/types/RecommendModel.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export type RecommendModel = 'related-products' | 'bought-together';
export type RecommendModel = 'related-products' | 'bought-together' | TrendingModel;
export type TrendingModel = 'trending-items' | 'trending-facets';
Comment on lines +1 to +2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export type RecommendModel = 'related-products' | 'bought-together' | TrendingModel;
export type TrendingModel = 'trending-items' | 'trending-facets';
export type TrendingModel = 'trending-items' | 'trending-facets';
export type RecommendModel = 'related-products' | 'bought-together' | TrendingModel;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry D: #1399

3 changes: 3 additions & 0 deletions packages/recommend/src/types/TrendingFacetsQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { TrendingQuery } from './TrendingQuery';

export type TrendingFacetsQuery = Omit<TrendingQuery, 'model' | 'facetValue'>;
3 changes: 3 additions & 0 deletions packages/recommend/src/types/TrendingItemsQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { TrendingQuery } from './TrendingQuery';

export type TrendingItemsQuery = Omit<TrendingQuery, 'model'>;
46 changes: 46 additions & 0 deletions packages/recommend/src/types/TrendingQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { TrendingModel } from './RecommendModel';
import { RecommendSearchOptions } from './RecommendSearchOptions';

export type TrendingQuery = {
/**
* The name of the target index.
*/
readonly indexName: string;

/**
* The name of the Recommendation model to use.
*/
readonly model: TrendingModel;

/**
* Threshold for the recommendations confidence score (between 0 and 100). Only recommendations with a greater score are returned.
*/
readonly threshold?: number;

/**
* How many recommendations to retrieve.
*/
readonly maxRecommendations?: number;

/**
* List of [search parameters](https://www.algolia.com/doc/api-reference/search-api-parameters/) to send.
*/
readonly queryParameters?: RecommendSearchOptions;

/**
* List of [search parameters](https://www.algolia.com/doc/api-reference/search-api-parameters/) to send.
*
* Additional filters to use as fallback when there aren’t enough recommendations.
*/
readonly fallbackParameters?: RecommendSearchOptions;

/**
* Used for trending model
*/
readonly facetName?: string;

/**
* Used for trending model
*/
readonly facetValue?: string;
};
18 changes: 18 additions & 0 deletions packages/recommend/src/types/WithRecommendMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { RequestOptions } from '@algolia/transporter';
import { FrequentlyBoughtTogetherQuery } from './FrequentlyBoughtTogetherQuery';
import { RecommendationsQuery } from './RecommendationsQuery';
import { RelatedProductsQuery } from './RelatedProductsQuery';
import { TrendingFacetsQuery } from './TrendingFacetsQuery';
import { TrendingItemsQuery } from './TrendingItemsQuery';

export type WithRecommendMethods<TType> = TType & {
/**
Expand All @@ -29,4 +31,20 @@ export type WithRecommendMethods<TType> = TType & {
queries: readonly FrequentlyBoughtTogetherQuery[],
requestOptions?: RequestOptions & SearchOptions
) => Readonly<Promise<MultipleQueriesResponse<TObject>>>;

/**
* Returns trending items
*/
readonly getTrendingItems: <TObject>(
queries: readonly TrendingItemsQuery[],
requestOptions?: RequestOptions & SearchOptions
) => Readonly<Promise<MultipleQueriesResponse<TObject>>>;

/**
* Returns trending items per facet
*/
readonly getTrendingFacets: <TObject>(
queries: readonly TrendingFacetsQuery[],
requestOptions?: RequestOptions & SearchOptions
) => Readonly<Promise<MultipleQueriesResponse<TObject>>>;
};
3 changes: 3 additions & 0 deletions packages/recommend/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ export * from './RecommendOptions';
export * from './RecommendSearchOptions';
export * from './RecommendationsQuery';
export * from './RelatedProductsQuery';
export * from './TrendingFacetsQuery';
export * from './TrendingQuery';
export * from './TrendingItemsQuery';
export * from './WithRecommendMethods';