Skip to content

Commit

Permalink
feat(multi-index): ease multi index and auto complete
Browse files Browse the repository at this point in the history
This commit simplifies the syntax that need to be used in order to do multi indices queries.
You can use multi indices either in your instant search page, or when building an autocomplete.

BREAKING CHANGES:
* Reseting the pagination should be done at each connector level inside the "refine" function when returning the search state.
* The current page now appears inside the search state when a widget is used
* Query values are part of the items prop of the connectCurrentRefinements connector. Behaviour is unchanged, query will be filtered if clearsQuery prop is false.
* Add the index name to all the current refinements items. (not used by our widgets yet, but available if needed).
  • Loading branch information
mthuret committed Mar 28, 2017
1 parent b4bc086 commit 09a4e1d
Show file tree
Hide file tree
Showing 72 changed files with 4,468 additions and 2,222 deletions.
2 changes: 2 additions & 0 deletions docgen/layouts/common/header.pug
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ nav.cm-navigation
ul#dropdown-1.simple-dropdown(role='tree', tabindex='-1')
li
a(href="widgets/InstantSearch.html", role='treeitem', data-link = 'true') #{'<InstantSearch>'}
li
a(href="widgets/<Index>.html", role='treeitem', data-link = 'true') #{'<Index>'}
li
a(href="widgets/", role='treeitem', data-link = 'true') Widgets
li
Expand Down
2 changes: 2 additions & 0 deletions docgen/layouts/mixins/nav.pug
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ mixin navRec(currentPath, navItems, title, depth, headings)
li(class=className)
if navItem.title === 'InstantSearch'
a(href=navItem.path class=activeClass)='<InstantSearch>'
else if navItem.title === 'Index'
a(href=navItem.path class=activeClass)='<Index>'
else
a(href=navItem.path class=activeClass)=navItem.title
ul
Expand Down
1 change: 1 addition & 0 deletions docgen/middlewares.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const common = [
reactPackage('src/widgets/*.js'),
reactPackage('src/connectors/*.js'),
reactPackage('src/core/InstantSearch.js'),
reactPackage('src/core/Index.js'),
], {
ignore: '**/*.test.js',
computeFilename: filename => `${filename}.jsdoc`, // denotes jsdoc file but also avoid js ignore
Expand Down
2 changes: 1 addition & 1 deletion docgen/plugins/jsdoc-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export default function() {
withHeadings: false,
layout: `${data.kind}.pug`,
category: data.kind,
navWeight: data.name === 'InstantSearch' ? 1000 : 0,
navWeight: data.name === 'InstantSearch' || data.name === 'Index' ? 1000 : 0,
};
});
});
Expand Down
1 change: 0 additions & 1 deletion docgen/plugins/sources.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export default function sourcesPlugin(sources, {ignore, computeFilename}) {
pluginDone(statErr);
return;
}

statDone(null, {...statMemo, [computeFilename(filename)]: {stats}});
});
},
Expand Down
34 changes: 23 additions & 11 deletions docgen/src/guide/Multi_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,37 @@ category: guide
navWeight: 50
---

You can use multiple [`<InstantSearch>`](guide/<InstantSearch>.html) instances for cases like:
Whenever you want to:

* displaying hits from different indices
* sharing a single SearchBox
* any use case involving synchronizing widgets between different [`<InstantSearch>`](guide/<InstantSearch>.html) instances
* display hits from different indices
* share a single SearchBox
* build an autocomplete menu targeting different indices

Two props on the [InstantSearch component](widgets/InstantSearch.html) can be used to inject searchState or be notified of searchState changes:
You can use multiple [`<Index>`](widgets/<Index>.html) instances.

* onSearchStateChange(onSearchStateChange): a function being called every time the [`<InstantSearch>`](guide/<InstantSearch>.html) searchState is updated.
* [searchState](guide/Search_state.html): a search state
The `<Index>` component takes one prop, the targeted index name.

The idea is to have a main component that will receive every new search state of the first instance
and then pass it back to each [`<InstantSearch>`](guide/<InstantSearch>.html) instances.
When using a `<Index>` component under an `<InstantSearch>` root component you can declare widgets that will target a precise index.

Refinements and parameters of an [`<InstantSearch>`](guide/<InstantSearch>.html) searchState needs to have their corresponding widgets or
[virtual widget](guide/Virtual_widgets.html) added to be effectively applied.
Widgets that targets all the indices, like the SearchBox, should remain under the `<InstantSearch>` root component.

[Read the example](https://github.com/algolia/instantsearch.js/tree/v2/packages/react-instantsearch/examples/multi-index) displaying hits from two different indices.

You might also want to:

* Use an external autocomplete component

In this case you will need to use the [`connectAutoComplete`](connectors/connectAutoComplete.html) connectors that will give you access to:

* All the indices hits
* The current query
* The refine function to update the query

[Read the example](https://github.com/algolia/instantsearch.js/blob/v2/packages/react-instantsearch/examples/autocomplete/src/App-Multi-Index.js) using AutoSuggest to display hits from different indices.

When using the `<Index>` component the shape of the search state will be modified. See
[our Search State guide](guide/Search_state.html).

<div class="guide-nav">
<div class="guide-nav-left">
Previous: <a href="guide/Search_parameters.html">← Search Parameters</a>
Expand Down
28 changes: 28 additions & 0 deletions docgen/src/guide/Search_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ Here's the `searchState` shape for all the connectors or widgets that we provide
max: 3000
}
},
configure: {
aroundLatLng: true,
},
refinementList: {
fruits: ['lemon', 'orange']
},
Expand All @@ -43,6 +46,31 @@ Here's the `searchState` shape for all the connectors or widgets that we provide
}
```

If you are performing a search on multiple indices using the [Index](widgets/<Index>.html)
component, you'll get the following shape:


```jsx
{
const searchState = {
query: 'ora', //shared state between all indices
page: 2, //shared state between all indices
indices: {
index1: {
configure: {
hitsPerPage: 3,
},
},
index2: {
configure: {
hitsPerPage: 10,
},
},
},
},
}
```

<div class="guide-nav">
<div class="guide-nav-left">
Previous: <a href="guide/Search_parameters.html">← Search parameters</a>
Expand Down
1 change: 1 addition & 0 deletions packages/react-instantsearch/connectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export {default as connectCurrentRefinements} from './src/connectors/connectCurr
export {default as connectHierarchicalMenu} from './src/connectors/connectHierarchicalMenu.js';
export {default as connectHighlight} from './src/connectors/connectHighlight.js';
export {default as connectHits} from './src/connectors/connectHits.js';
export {default as connectAutoComplete} from './src/connectors/connectAutoComplete.js';
export {default as connectHitsPerPage} from './src/connectors/connectHitsPerPage.js';
export {default as connectInfiniteHits} from './src/connectors/connectInfiniteHits.js';
export {default as connectMenu} from './src/connectors/connectMenu.js';
Expand Down
6 changes: 6 additions & 0 deletions packages/react-instantsearch/dom.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import createInstantSearch from './src/core/createInstantSearch';
import createIndex from './src/core/createIndex';
import algoliasearch from 'algoliasearch/lite';

const InstantSearch = createInstantSearch(algoliasearch, {
Root: 'div',
props: {className: 'ais-InstantSearch__root'},
});
export {InstantSearch};
const Index = createIndex({
Root: 'div',
props: {className: 'ais-MultiIndex__root'},
});
export {Index};
export {default as Configure} from './src/widgets/Configure.js';
export {default as CurrentRefinements} from './src/widgets/CurrentRefinements.js';
export {default as HierarchicalMenu} from './src/widgets/HierarchicalMenu.js';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,45 @@ body {
font-family: Helvetica, sans-serif;
}

.highlighted{
background: yellow;
}

.autocomplete{
display: flex;
justify-content: space-between;
border: 1px solid red;
}

.content{
display: flex;
justify-content: space-between;
}

.block{
padding: 5px 10px;
}

.title{
border: 1px solid red;
display: flex;
justify-content: space-around;
padding: 5px 10px;
}

.disabled {
display: none;
}

.ais-MultiIndex__root{
width: 100%;
}

.title div{
width: 100%;
padding: 5px 10px;
}

.react-autosuggest__container {
position: relative;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Autosuggest from 'react-autosuggest';
import {forOwn} from 'lodash';
import 'react-instantsearch-theme-algolia/style.css';

class App extends Component {
class App2 extends Component {
render() {
return (
<InstantSearch
Expand Down Expand Up @@ -41,10 +41,10 @@ const connectAutoComplete = createConnector({
facets you want the value of.
*/
getProvidedProps(props, state, search) {
const hits = search.results ? search.results.hits : [];
const hits = search.results && search.results.bestbuy ? search.results.bestbuy.hits : [];
const facets = props.attributes.reduce((acc, attributeName) => {
if (search.results) {
acc[attributeName] = search.results
if (search.results && search.results.bestbuy) {
acc[attributeName] = search.results.bestbuy
.getFacetValues(attributeName)
.slice(0, 3)
.map(v => ({
Expand Down Expand Up @@ -107,4 +107,4 @@ AutoComplete.propTypes = {

const ConnectedAutoComplete = connectAutoComplete(AutoComplete);

export default App;
export default App2;

0 comments on commit 09a4e1d

Please sign in to comment.