Skip to content

Commit 36bbcfc

Browse files
feat(recommend): Add trending types and methods
1 parent 326c833 commit 36bbcfc

18 files changed

+277
-6
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { TestSuite } from '../../../client-common/src/__tests__/TestSuite';
2+
3+
const recommend = new TestSuite('recommend').recommend;
4+
5+
function createMockedClient() {
6+
const client = recommend('appId', 'apiKey');
7+
jest.spyOn(client.transporter, 'read').mockImplementation(() => Promise.resolve());
8+
9+
return client;
10+
}
11+
12+
describe('getTrendingFacets', () => {
13+
test('builds the request', async () => {
14+
const client = createMockedClient();
15+
16+
await client.getTrendingFacets(
17+
[
18+
{
19+
indexName: 'products',
20+
facetName: 'company',
21+
},
22+
],
23+
{}
24+
);
25+
26+
expect(client.transporter.read).toHaveBeenCalledTimes(1);
27+
expect(client.transporter.read).toHaveBeenCalledWith(
28+
{
29+
cacheable: true,
30+
data: {
31+
requests: [
32+
{
33+
indexName: 'products',
34+
model: 'trending-facets',
35+
facetName: 'company',
36+
threshold: 0,
37+
},
38+
],
39+
},
40+
method: 'POST',
41+
path: '1/indexes/*/recommendations',
42+
},
43+
{}
44+
);
45+
});
46+
});
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { TestSuite } from '../../../client-common/src/__tests__/TestSuite';
2+
3+
const recommend = new TestSuite('recommend').recommend;
4+
5+
function createMockedClient() {
6+
const client = recommend('appId', 'apiKey');
7+
jest.spyOn(client.transporter, 'read').mockImplementation(() => Promise.resolve());
8+
9+
return client;
10+
}
11+
12+
describe('getTrendingGlobalItems', () => {
13+
test('builds the request', async () => {
14+
const client = createMockedClient();
15+
16+
await client.getTrendingGlobalItems(
17+
[
18+
{
19+
indexName: 'products',
20+
},
21+
],
22+
{}
23+
);
24+
25+
expect(client.transporter.read).toHaveBeenCalledTimes(1);
26+
expect(client.transporter.read).toHaveBeenCalledWith(
27+
{
28+
cacheable: true,
29+
data: {
30+
requests: [
31+
{
32+
indexName: 'products',
33+
model: 'trending-items',
34+
threshold: 0,
35+
},
36+
],
37+
},
38+
method: 'POST',
39+
path: '1/indexes/*/recommendations',
40+
},
41+
{}
42+
);
43+
});
44+
});
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { TestSuite } from '../../../client-common/src/__tests__/TestSuite';
2+
3+
const recommend = new TestSuite('recommend').recommend;
4+
5+
function createMockedClient() {
6+
const client = recommend('appId', 'apiKey');
7+
jest.spyOn(client.transporter, 'read').mockImplementation(() => Promise.resolve());
8+
9+
return client;
10+
}
11+
12+
describe('getTrendingItemsForFacet', () => {
13+
test('builds the request', async () => {
14+
const client = createMockedClient();
15+
16+
await client.getTrendingItemsForFacet(
17+
[
18+
{
19+
indexName: 'products',
20+
facetName: 'company',
21+
facetValue: 'tesla',
22+
},
23+
],
24+
{}
25+
);
26+
27+
expect(client.transporter.read).toHaveBeenCalledTimes(1);
28+
expect(client.transporter.read).toHaveBeenCalledWith(
29+
{
30+
cacheable: true,
31+
data: {
32+
requests: [
33+
{
34+
indexName: 'products',
35+
model: 'trending-items',
36+
facetName: 'company',
37+
facetValue: 'tesla',
38+
threshold: 0,
39+
},
40+
],
41+
},
42+
method: 'POST',
43+
path: '1/indexes/*/recommendations',
44+
},
45+
{}
46+
);
47+
});
48+
});

packages/recommend/src/builds/browser.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@ import { createBrowserXhrRequester } from '@algolia/requester-browser-xhr';
88
import { createUserAgent } from '@algolia/transporter';
99

1010
import { createRecommendClient } from '../createRecommendClient';
11-
import { getFrequentlyBoughtTogether, getRecommendations, getRelatedProducts } from '../methods';
11+
import {
12+
getFrequentlyBoughtTogether,
13+
getRecommendations,
14+
getRelatedProducts,
15+
getTrendingFacets,
16+
getTrendingGlobalItems,
17+
getTrendingItemsForFacet,
18+
} from '../methods';
1219
import { BaseRecommendClient, RecommendOptions, WithRecommendMethods } from '../types';
1320

1421
export default function recommend(
@@ -47,6 +54,9 @@ export default function recommend(
4754
getFrequentlyBoughtTogether,
4855
getRecommendations,
4956
getRelatedProducts,
57+
getTrendingFacets,
58+
getTrendingGlobalItems,
59+
getTrendingItemsForFacet,
5060
},
5161
});
5262
}

packages/recommend/src/builds/node.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@ import { createNodeHttpRequester } from '@algolia/requester-node-http';
77
import { createUserAgent } from '@algolia/transporter';
88

99
import { createRecommendClient } from '../createRecommendClient';
10-
import { getFrequentlyBoughtTogether, getRecommendations, getRelatedProducts } from '../methods';
10+
import {
11+
getFrequentlyBoughtTogether,
12+
getRecommendations,
13+
getRelatedProducts,
14+
getTrendingFacets,
15+
getTrendingGlobalItems,
16+
getTrendingItemsForFacet,
17+
} from '../methods';
1118
import { BaseRecommendClient, RecommendOptions, WithRecommendMethods } from '../types';
1219

1320
export default function recommend(
@@ -41,6 +48,9 @@ export default function recommend(
4148
getFrequentlyBoughtTogether,
4249
getRecommendations,
4350
getRelatedProducts,
51+
getTrendingFacets,
52+
getTrendingGlobalItems,
53+
getTrendingItemsForFacet,
4454
},
4555
});
4656
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { BaseRecommendClient, TrendingFacetsQuery, WithRecommendMethods } from '../types';
2+
import { getRecommendations } from './getRecommendations';
3+
4+
type GetTrendingFacets = (
5+
base: BaseRecommendClient
6+
) => WithRecommendMethods<BaseRecommendClient>['getTrendingFacets'];
7+
8+
export const getTrendingFacets: GetTrendingFacets = base => {
9+
return (queries: readonly TrendingFacetsQuery[], requestOptions) => {
10+
return getRecommendations(base)(
11+
queries.map(query => ({
12+
...query,
13+
model: 'trending-facets',
14+
})),
15+
requestOptions
16+
);
17+
};
18+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { BaseRecommendClient, TrendingGlobalItemsQuery, WithRecommendMethods } from '../types';
2+
import { getRecommendations } from './getRecommendations';
3+
4+
type GetTrendingGlobalItems = (
5+
base: BaseRecommendClient
6+
) => WithRecommendMethods<BaseRecommendClient>['getTrendingGlobalItems'];
7+
8+
export const getTrendingGlobalItems: GetTrendingGlobalItems = base => {
9+
return (queries: readonly TrendingGlobalItemsQuery[], requestOptions) => {
10+
return getRecommendations(base)(
11+
queries.map(query => ({
12+
...query,
13+
model: 'trending-items',
14+
})),
15+
requestOptions
16+
);
17+
};
18+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { BaseRecommendClient, TrendingItemsForFacetQuery, WithRecommendMethods } from '../types';
2+
import { getRecommendations } from './getRecommendations';
3+
4+
type GetTrendingItemsForFacet = (
5+
base: BaseRecommendClient
6+
) => WithRecommendMethods<BaseRecommendClient>['getTrendingItemsForFacet'];
7+
8+
export const getTrendingItemsForFacet: GetTrendingItemsForFacet = base => {
9+
return (queries: readonly TrendingItemsForFacetQuery[], requestOptions) => {
10+
return getRecommendations(base)(
11+
queries.map(query => ({
12+
...query,
13+
model: 'trending-items',
14+
})),
15+
requestOptions
16+
);
17+
};
18+
};

packages/recommend/src/methods/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@
55
export * from './getFrequentlyBoughtTogether';
66
export * from './getRecommendations';
77
export * from './getRelatedProducts';
8+
export * from './getTrendingFacets';
9+
export * from './getTrendingGlobalItems';
10+
export * from './getTrendingItemsForFacet';

packages/recommend/src/types/FrequentlyBoughtTogetherQuery.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ import { RecommendationsQuery } from './RecommendationsQuery';
22

33
export type FrequentlyBoughtTogetherQuery = Omit<
44
RecommendationsQuery,
5-
'model' | 'fallbackParameters'
5+
'model' | 'fallbackParameters' | 'facetName' | 'facetValue'
66
>;
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
export type RecommendModel = 'related-products' | 'bought-together';
1+
export type RecommendModel =
2+
| 'related-products'
3+
| 'bought-together'
4+
| 'trending-items'
5+
| 'trending-facets';

packages/recommend/src/types/RecommendationsQuery.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export type RecommendationsQuery = {
1515
/**
1616
* The `objectID` of the item to get recommendations for.
1717
*/
18-
readonly objectID: string;
18+
readonly objectID?: string;
1919

2020
/**
2121
* Threshold for the recommendations confidence score (between 0 and 100). Only recommendations with a greater score are returned.
@@ -38,4 +38,14 @@ export type RecommendationsQuery = {
3838
* Additional filters to use as fallback when there aren’t enough recommendations.
3939
*/
4040
readonly fallbackParameters?: RecommendSearchOptions;
41+
42+
/**
43+
* Used for trending model
44+
*/
45+
readonly facetName?: string;
46+
47+
/**
48+
* Used for trending model
49+
*/
50+
readonly facetValue?: string;
4151
};
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
import { RecommendationsQuery } from './RecommendationsQuery';
22

3-
export type RelatedProductsQuery = Omit<RecommendationsQuery, 'model'>;
3+
export type RelatedProductsQuery = Omit<RecommendationsQuery, 'model' | 'facetName' | 'facetValue'>;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { RecommendationsQuery } from './RecommendationsQuery';
2+
3+
export type TrendingFacetsQuery = Omit<RecommendationsQuery, 'model' | 'objectID' | 'facetValue'>;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { RecommendationsQuery } from './RecommendationsQuery';
2+
3+
export type TrendingGlobalItemsQuery = Omit<
4+
RecommendationsQuery,
5+
'model' | 'objectID' | 'facetName' | 'facetValue'
6+
>;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { RecommendationsQuery } from './RecommendationsQuery';
2+
3+
export type TrendingItemsForFacetQuery = Omit<RecommendationsQuery, 'model' | 'objectID'>;

packages/recommend/src/types/WithRecommendMethods.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { RequestOptions } from '@algolia/transporter';
44
import { FrequentlyBoughtTogetherQuery } from './FrequentlyBoughtTogetherQuery';
55
import { RecommendationsQuery } from './RecommendationsQuery';
66
import { RelatedProductsQuery } from './RelatedProductsQuery';
7+
import { TrendingFacetsQuery } from './TrendingFacetsQuery';
8+
import { TrendingGlobalItemsQuery } from './TrendingGlobalItemsQuery';
9+
import { TrendingItemsForFacetQuery } from './TrendingItemsForFacetQuery';
710

811
export type WithRecommendMethods<TType> = TType & {
912
/**
@@ -29,4 +32,28 @@ export type WithRecommendMethods<TType> = TType & {
2932
queries: readonly FrequentlyBoughtTogetherQuery[],
3033
requestOptions?: RequestOptions & SearchOptions
3134
) => Readonly<Promise<MultipleQueriesResponse<TObject>>>;
35+
36+
/**
37+
* Returns trending items
38+
*/
39+
readonly getTrendingGlobalItems: <TObject>(
40+
queries: readonly TrendingGlobalItemsQuery[],
41+
requestOptions?: RequestOptions & SearchOptions
42+
) => Readonly<Promise<MultipleQueriesResponse<TObject>>>;
43+
44+
/**
45+
* Returns trending items per facet
46+
*/
47+
readonly getTrendingItemsForFacet: <TObject>(
48+
queries: readonly TrendingItemsForFacetQuery[],
49+
requestOptions?: RequestOptions & SearchOptions
50+
) => Readonly<Promise<MultipleQueriesResponse<TObject>>>;
51+
52+
/**
53+
* Returns trending items per facet
54+
*/
55+
readonly getTrendingFacets: <TObject>(
56+
queries: readonly TrendingFacetsQuery[],
57+
requestOptions?: RequestOptions & SearchOptions
58+
) => Readonly<Promise<MultipleQueriesResponse<TObject>>>;
3259
};

packages/recommend/src/types/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@ export * from './RecommendOptions';
1010
export * from './RecommendSearchOptions';
1111
export * from './RecommendationsQuery';
1212
export * from './RelatedProductsQuery';
13+
export * from './TrendingFacetsQuery';
14+
export * from './TrendingGlobalItemsQuery';
15+
export * from './TrendingItemsForFacetQuery';
1316
export * from './WithRecommendMethods';

0 commit comments

Comments
 (0)