Can't perform facet count, as no facet is set Meilisearch - instantsearch.js

I am trying to do refinement in meilisearch.
const search = instantsearch({
indexName: "books",
searchClient: instantMeiliSearch(
"https://example.com",
"XXXXXXXXXXX",
),
searchParameters: {
attributesForFaceting: ['title']
}
});
instantsearch.widgets.refinementList({
container: '#brand-list',
attribute: 'title',
}),
I am keep getting error 'Can't perform facet count, as no facet is set'. I do not know what I am doing wrong, any help would be great.
Thanks in advance.

You must add attributesForFacetting to the settings to be able to perform a search with facet filters. Check the dedicated section of the documentation: https://docs.meilisearch.com/reference/features/faceted_search.html#setting-up-facets

Related

Vuetify / Vue (2) data table not sorting / paginating upon new bound prop

Keeping the table as basic as possible to figure this out. I am struggling to learn how to create server side sorting/pagination to function in vuetify. When I add the :options or :server-items-length bind the table no longer sorts or paginates.
Without either of those, I get a default listing of 10 items per row - and the sorting all works perfectly fine as well the pagination. However, parameters in the api require a page item count thus forcing a hardcoded number or using the :options bind. If i just place a hard coded number things work fine, but when I bind I get proper items per page but no sorting and pagination.
Very simple data table:
<v-data-table
:items="ItemResults.items"
:headers="TableData.TableHeaders"
:loading="TableData.isLoading"
>
</v-data-table>
//Base data returns, with headers and options as well the array that items are stored in.
data() {
return {
ItemResults:[],
TableData: {
isLoading: true,
TableHeaders: [
{ value: "title", text: "Title" },
{ value: 'artist', text: 'Artist' },
{ value: 'upc', text: 'UPC' },
{ value: "retailPrice", text: "Price/Quantity"},
],
},
options:
{
page: 1,
itemsPerPage: 15
},
}
},
//Then last, my async method to grab the data from the api, and place it in the itemresults array.
async getProducts(){
this.TableData.isLoading = true;
const { page, itemsPerPage } = this.options;
var temp = await this.$axios.get(`Inventory/InventoryListing_inStock/1/${page}/${itemsPerPage}`);
this.ItemResults = temp.data;
this.TableData.isLoading = false;
return this.ItemResults;
},
I have tried following Vuetify Pagination and sort serverside guide, but I'm not sure where they are recommending to make the axios call.
The lead backend dev is working on setting a sorting function up in the api for me to call paramaters to as well - Im not sure how that will function along side.
but I dont know how to have this controlled by vuetify eithier, or the best practice here.
EDIT:
I've synced the following:
:options.sync="options"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
but i think I dont need to sync the last two. My options:
options:
{
page: 1,
itemsPerPage: 15,
sortBy: ['title'],
sortDesc: [false]
},
and in my data I put the array for sort by and sort desc
sortBy: [
'title', 'artist', 'upc', 'retailPrice'
],
sortDesc:[true, false],
pagination is now working, and sort ascending is now working, but when I click to descend the header I get an error that the last two params are empty on update to / / instead of /sortBy/sortDesc result. So its not listing the values on changes.
When your component mounts, you need to fetch the total number of items available on the server and the first page of data, and set these as :items and :server-items-length. The latter will (as you observed) disable paging and sorting, as your server will take care of it, and it is used to calculate the total number of pages given a selected page size.
Now you need to know when to reload data. For this, you either bind options to the v-data-table with two-way binding (.sync) and set a watcher on it, or you listen to the update:options event. And whenever options change, you fetch the selected data from the server.
That's basically all it takes.
In your template:
<v-data-table
:items="items"
:headers="headers"
:loading="true"
:server-items-length="numberOfItemsOnServer"
#update:options="options => loadPage(options)"
/>
In your component:
methods: {
async loadPage(options){
this.items = [] // if you want to show DataTable's loading-text
this.items = await fetch('yourUrl' + new URLSearchParams({
// build url params from the options object
offset: (options.page - 1) * options.itemsPerPage,
limit: options.itemsPerPage,
orderBy: options.sortBy.map((sb,ix) => [sb, options.sortDesc[ix] ? 'desc' : 'asc'])
}))
}
}

Is it possible to query document schema metadata in Sanity/GROQ?

I have a simple singleton document schema defined in my Sanity/NextJS project, to model my "Colophon" page (richText is a custom block field type):
export default {
title: 'Colophon',
name: 'colophon',
type: 'document',
__experimental_actions: ['update', 'publish'],
fields: [
{
title: 'Body',
name: 'body',
type: 'richText',
validation: Rule => Rule.required(),
},
],
};
I retrieve this document with a simple query in my NextJS application:
export async function getStaticProps() {
const colophon = await client.fetch(`
*[_type == "colophon"][0]
`);
// ...
};
Is it possible to write a GROQ query to retrieve the meta title defined in the schema, i.e. Colophon? Although this is a singleton document, I would like to avoid repeating this string in my project if possible. At the moment, I can only see the fields on the document in my results, i.e. body.
Thanks for reading!
No, I don't believe there is.
As far as I understand what you're after; The schema is defined in the studio-instance and not the datastore. Those two are not hard coupled. I have several studio-instances with small variations on the schemas using one single project/datastore. The API you query to get data does not care which studio and schema was used and cant answer for the actual schema details.

How to Fetch data to dynamically build out a custom Menu for a Layout?

What I would like to do is, call an endpoint to get the list of categories to display in the Sidebar's Menu. I'm not seeing anything in the Layout that would handle this. Am I missing something? What would be the correct way to do this?
Thanks #François, good to know I don't need to look any further in the Layout or Menu files.
Looking at the Demo source code, I see this approach in action using Reacts useState and useEffect.
Posted for others, this is in my Admin component:
const [categories, setCategories] = useState({categories: []});
useEffect(
() => {
dataProvider.getList('tools', {
sort: '',
pagination: {
page: 1,
perPage: 10
}
}).then(data =>
setCategories({categories: data['data']}))
},
[]
);

Docusaurus single level sidebar

I'm building a website with Docusaurus V2.
Here is my sidebars.js:
module.exports = {
docs: {
'10 Studio': ['introduction'],
'Getting Started': ['trySamples', 'installation'],
'Formula Editor': ['formulaEditor'],
'Spreadsheet Verificator': ['spreadsheetVerificator'],
'Bottleneck Detector': ['bottleneckDetector'],
'Spreadsheet Optimizer': ['spreadsheetOptimizer'],
'Contact & Community': ['contactAndCommunity'],
},
};
The result is as follows. As we can see, for Spreadsheet Verificator, Bottleneck Detector, etc., a second level is not necessary. Does anyone know how we could make them only one level?
I'm still working on this. A more flexible format will be available in future.
You could use the following for a single level:
{
type: 'ref'
id: 'spreadsheetVerificator'
}

rally search user by first character

I want to realize the functionality that we can search the users' name by typing in the first character of their names. I need to use Javascript to create a custom html.
Is there anyone who has done this before could help me?
In the example from this repository, a user combobox Rally.ui.combobox.UserComboBox searches for matching values dynamically based on the first couple of characters.
This default functionality displays the expected values after the second character is entered.
var u = Ext.create('Rally.ui.combobox.UserComboBox',{
id: 'u',
project: project,
fieldLabel: 'select user',
listeners:{
ready: function(combobox){
this._onUserSelected(combobox.getRecord());
},
select: function(combobox){
this._onUserSelected(combobox.getRecord());
},
scope: this
}
});
this.add(u);
},
If you want to load all users (do not limit the selection to team members and editors of a specific project) you may use Rally.ui.combobox.Combobox instead of Rally.ui.combobox.UserComboBox, and set the model to User. But to workaround a default behavior where only the current user populates the combobox, use a filter that would filter in all users. In the example below ObjectID > 0 is used. This combobox will be populated by all users independently of the project picker. This fragment is not a part of a custom app example above:
{
xtype: 'rallycombobox',
fieldLabel: 'select project',
storeConfig: {
autoLoad: true,
model: 'User',
filters:[
{
property: 'ObjectID',
operator: '>',
value: 0
}
],
sorters: [
{
property: 'UserName',
direction: 'ASC'
}
]
}
}
You'll want to use the Web Services API. Here's how I would do it...
The API doesn't allow you to specify a placement of a character in the filter, but you can require that it exists somewhere in the name, that filter would look like:
[{
property : "FirstName",
operator : "contains",
value : "A" //Whatever letter you're looking to start with
}]
Now, once the store is loaded, use a second function to filter the records to only those which start with your character:
store.filterBy(function(item) {
return item.get("FirstName")[0] === "A";
});
Hope this helps :)