Skip to content

Commit

Permalink
feat(recommend): Add trending types and methods (#1396)
Browse files Browse the repository at this point in the history
Co-authored-by: Clément Vannicatte <20689156+shortcuts@users.noreply.github.com>
  • Loading branch information
SophieManley03 and shortcuts committed Mar 14, 2022
1 parent ede7a4b commit 6882ec8
Show file tree
Hide file tree
Showing 15 changed files with 258 additions and 7 deletions.
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';
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';

0 comments on commit 6882ec8

Please sign in to comment.