Listpaging in Sencha Touch using 'offset' instead of 'page' - pagination

I am using listpaging plugin on a list and would like to use it with an 'offset' value. The API that I'm running against doesn't support pagination with 'page' values but rather uses offsets.
If I have a limit of 10 and offset 0, I will get the first 10 records, with limit 10 and offset 10, I will get records 11-20 and so on.
The listpaging plugin though requires a 'page' value. I have tried setting the startParam to 'offset' on my store proxy but this results in loading records 1-11 rather than 11-20.
Any suggestions?
Ext.define('MyApp.store.Retailers', {
extend: 'Ext.data.Store',
config: {
storeId: 'retailersStore',
model: 'MyApp.model.Retailer',
pageSize: 10,
proxy: {
type: 'ajax',
method: 'GET',
url: 'myapp/api/retailers',
startParam: 'offset',
reader: {
type: 'json',
rootProperty: 'data.entries',
totalProperty: 'count'
}
}
}
});

In that case, you can add pageParam: 'customPageParamName' property to proxy and voilĂ .
Hope this helps.

Related

Faunadb how do I paginate an index sorted by Timestamp

I created an index on faunadb to sort by the time stamp in order to get the most recent items first, and I am trying to retrieve 100 items at a time. My problem is that when I enter the "after" parameter from the result, I receive the same results as the initial query.
This is the index I created:
CreateIndex({
name: "all_school_queries",
source: Collection('<school_queries_reversed>'),
values: values: [
{
field: ["ts", {reverse: true}]
},
{
field: ["ref"]
}
]
})
This is how I am querying the database:
Map(
Paginate(Match(Index("school_query_reverse")), {
after: [ Ref(Collection("collection_name") ,'collection ref from first query')],
}),
Lambda(
['ts',"ref"],
Get(Var("ref"))
)
)
and this is the first result:
{
before: [Ref(Collection("collection_name"), "275484304279077376")],
after: [
1598907150720000,
Ref(Collection("school_queries"), "12345"),
Ref(Collection("school_queries"), "12345")
],
}
I have used both the timestamp for the after, 1598907150720000 and the ref, 12345. I tried the console first to make sure I could get the right response, but upon entering the either result from the after, I get the same result.
I'll try to answer your question (I'm the dev adv at FaunaDB). I have to say that I'm quite confused by your question due to syntax that doesn't seem to make sense to me, so I apologize if it's not the answer you are looking for.
Things that I'm confused by.
The index syntax is wrong, did you copy this somewhere or did you rewrite this manually? If you copied it somewhere then we might display it wrongly so do let me know if that's the case. The index name does not match the name you are using so I assume this is a typo.
<school_queries_reversed>, reversed in the collection name doesn't seem to make sense to me since reverse is defined on the index, not on the collection.
Doesn't matter though, I tried to reproduce your issue, since I don't have an idea how the data looks I kept it simple.
The index I used looks as follows:
CreateIndex({
name: "all_school_queries",
source: Collection('school_queries'),
values: [
{
field: ["ts"],
reverse: true
},
{
field: ["ref"]
}
]
})
If I then query this index as follows:
Map(
Paginate(Match(Index("all_school_queries")), {size: 1}),
Lambda(
['ts',"ref"],
Get(Var("ref"))
)
)
I do get the last element I added first (reverse index)
{
after: [
1599220462170000,
Ref(Collection("school_queries"), "275735235372515847"),
Ref(Collection("school_queries"), "275735235372515847")
],
data: [
{
ref: Ref(Collection("school_queries"), "275735244842205703"),
ts: 1599220471200000,
data: {
query: "bli"
}
}
]
}
and when I use the returned after cursor to get the next page (I have specified pages of only one element here):
Map(
Paginate(Match(Index("all_school_queries")), {size: 1, after: [
1599220462170000,
Ref(Collection("school_queries"), "275735235372515847"),
Ref(Collection("school_queries"), "275735235372515847")
]}),
Lambda(
['ts',"ref"],
Get(Var("ref"))
)
)
I do get (as expected) the other element.
{
before: [
1599220462170000,
Ref(Collection("school_queries"), "275735235372515847"),
Ref(Collection("school_queries"), "275735235372515847")
],
data: [
{
ref: Ref(Collection("school_queries"), "275735235372515847"),
ts: 1599220462170000,
data: {
query: "bla"
}
}
]
}
Is that not working for you?
I had the same problem and created a forum post on how to deal with it.
https://forums.fauna.com/t/filter-by-timestamp-with-gql-resolver/3302
I guess most people are missing
paginated: true in the gql schema or
Map(Var("page"), Lambda(["ts", "ref"], Get(Var("ref")))) to pass ["ts", "ref"] to the lambda after pagination

Does EdgeNGram autocomplete_filter make sense with prefix search?

i have Elastic Search Index with around 1 million records.
I want to do multi prefix search against 2 fields in the Elastic Search Index, Name and ID (there are around 10 total).
Does creating EdgeNGram autocomplete filter make sense at all?
Or i am missing the point of the EdgeNGram.
Here is the code i have for creation of the index:
client.indices.create({
index: 'testing',
// type: 'text',
body: {
settings: {
analysis: {
filter: {
autocomplete_filter: {
type: 'edge_ngram',
min_gram: 3,
max_gram: 20
}
},
analyzer: {
autocomplete: {
type: 'custom',
tokenizer: 'standard',
filter: [
'lowercase',
'autocomplete_filter'
]
}
}
}
}
}
},function(err,resp,status) {
if(err) {
console.log(err);
}
else {
console.log("create",resp);
}
});
Code for searching
client.search({
index: 'testing',
type: 'article',
body: {
query: {
multi_match : {
query: "87041",
fields: [ "name", "id" ],
type: "phrase_prefix"
}
}
}
},function (error, response,status) {
if (error){
console.log("search error: "+error)
}
else {
console.log("--- Response ---");
console.log(response);
console.log("--- Hits ---");
response.hits.hits.forEach(function(hit){
console.log(hit);
})
}
});
The search returns the correct results, so my question being does creating the edgengram filter and analyzer make sense in this case?
Or this prefix functionality would be given out of the box?
Thanks a lot for your info
It is depending on your use case. Let me explain.
You can use ngram for this feature. Let's say your data is london bridge, then if your min gram is 1 and max gram is 20, it will be tokenized as l, lo, lon, etc..
Here the advantage is that even if you search for bridge or any tokens which is part of the generated ngrams, it will be matched.
There is one out of box feature completion suggester. It uses FST model to store them. Even the documentation says it is faster to search but costlier to build. But the think is it is prefix suggester. Meaning searching bridge will not bring london bridge by default. But there are ways to make this work. Workaround to achieve is that, to have array of tokens. Here london bridge and bridge are the tokens.
There is one more called context suggester. If you know that you are going to search on name or id, it is best over completion suggester. As completion suggester works over on all the index, context suggester works on a particular index based on the context.
As you say, it is prefix search you can go for completion. And you mentioned that there 10 such fields. And if you know the field to be suggested at fore front, then you can go for context suggester.
one nice answer about edge ngram and completion
completion suggester for middle of the words - I used this solution, it works like charm.
You can refer documentation for other default options available within suggesters.

How to display limited entity in AUI: Autocomplete search suggetion

To search user by userId i am using aui: autocomplete, Is there any attribute available to display a limit number of entities in search result as i have a large number of users and while searching it is taking too much of time to load it.
new A.AutoCompleteList(
{
allowBrowserAutocomplete: 'true',
inputNode: '#search_id',
resultTextLocator: 'userId',
render: 'true',
resultHighlighter: 'phraseMatch',
resultFilters:['phraseMatch'],
source:userAgList,
})
Looking at the AutoCompleteList documentation: https://alloyui.com/api/classes/AutoCompleteList.html it seems that there is an attribute for this: maxResults.
Probably using it at the end of your code is enough:
new A.AutoCompleteList(
{
allowBrowserAutocomplete: 'true',
inputNode: '#search_id',
resultTextLocator: 'userId',
render: 'true',
resultHighlighter: 'phraseMatch',
resultFilters:['phraseMatch'],
source:userAgList,
maxResults: 20
})
Anyway this solution may change depending on the version of AlloyUI.

Highcharts - Hide child labels in a multiple levels and multiple layouts treemap

On highcharts, I have a treemap with 2 levels, each with a different layout algorithm. Now I want to limit what we can see to the current level. It means that on level 1, I don't want to see the labels of level 2, which would only appear when drilling down (and the labels of level 1 would disappear).
I know it is easy with levelIsConstant: false, but this only works with 1 level, and I use 2 because I need different layouts.
Here is the link to what I currently have:
series: [{
type: "treemap",
allowDrillToNode: true,
alternateStartingDirection: true,
levels: [{
level: 1,
layoutAlgorithm: 'squarified',
dataLabels: {
enabled: true,
align: 'left',
verticalAlign: 'top',
style: {
fontSize: '15px',
fontWeight: 'bold'
}
}
}, {
level: 2,
layoutAlgorithm: 'stripes',
color: 'blue'
}],
//...
http://jsfiddle.net/dhfera2y/2/
I want all the names to be hidden, as well as the lines separating them.
EDIT: Using a rgba color on each level, I can hide the nodes below it, but I still cannot hide their label!
Thank you it is a smart idea for the labels issue, but as I say I cannot use levelIsConstant: false because I need a different layout for each level at every moment. With this solution both levels can have a different layout when I am on the top level, but I soon as I drill down I loose the correct layout for the new view.
Almost :-)
EDIT : Okay so I finally managed to do it. I think it is impossible to achieve this in the way I was trying to, which was using the parent option for each child point of the serie in order to determine the hierarchy of the tree. So instead of using one serie with a hierarchy, I use one serie for the top level which I link to several series for the level below.
I was able the do this thanks to the drilldown option.
I found the solution in the official documentation :
http://www.highcharts.com/docs/chart-concepts/drilldown
I adjusted the code and it was all right. Here is the solution I came up with (it is a different work from my first link) :
http://jsfiddle.net/ff964fog/47/
series: [{
type: 'treemap',
layoutAlgorithm: 'squarified',
borderWidth: 3,
data: modulesData
}],
drilldown: {
series: servicesSerie
},
I still have to adjust a few things (like the disappearance of the animations for the bottom level), but in the end I have exactly what I wanted !
My take on some settings you can use to achieve this (JSFiddle):
series: [{
type: "treemap",
allowDrillToNode: true,
levelIsConstant: false,
// ...
levels: [{
level: 1,
dataLabels: {
enabled: true
}
// ...
}, {
level: 2,
borderWidth: 0,
dataLabels: {
enabled: false
}
}],
data[{
//...
}]
}]
The level 2 settings apply only when viewing from level 1. When drilling down the new view is considered to be level 1 because of levelIsConstant: false.
Setting borderWidth: 0 in level 2 is only needed if you want to hide the grid of level 2 when viewing from level 1.
You can use a custom formatter for plotOptions.treemap.datalabels. The code bellow is an example that uses this.series.rootNode and this.point.parent and compare them to examine if the label should be shown or not:
plotOptions: {
treemap: {
dataLabels: {
formatter: function(data) {
if (this.point.parent == (this.series.rootNode || null)) {
return this.key;
}
}
}
}
}
You can use any other property that is available in formatter function. Just log (console.log) this and data in the formatter function to see all the properties available:
plotOptions: {
treemap: {
dataLabels: {
formatter: function(data) {
console.log(this, data);
}
}
}
}

Autocomplete using values from AJAX

I have a table using tabulator.
Everything works great, but I am trying to get autocomplete working with Ajax
What I am trying is:
var customerNumbers = [];
var table = new Tabulator("#edi-table",
ajaxURL: baseUrl + '/PaginatedEndPoint',
pagination: "remote",
paginationSize: 30,
paginationSizeSelector: [30, 60, 100, 200],
ajaxSorting: true,
ajaxFiltering: true,
selectable: true,
cellEdited: function (cell) {
cell.getElement().style.backgroundColor = "#32CD32";
},
dataLoading: function () {
customerNumbers = ["11", "12", "13"];
},
columns: [
{
title: "CustomerNumber", field: "CustomerNumber", headerFilter: "input", editor: "autocomplete", editorParams: {
searchFunc: function (term, values) {
var matches = [];
values.forEach(function (item) {
if (item.value === term) {
matches.push(item);
}
});
console.log(matches);
return matches;
},
listItemFormatter: function (value, title) {
return "Mr " + title;
},
values: customerNumbers
}
}
]
However, this does not show any predictions value predictions for me, it seems that autocomplete is built before "dataLoading" or any other Callback (I have tried many) is called.
I have tried to make an auxilary array in the style of values like {Title: "Mr + title", value: "title"} and then assign it in the searchFunc, and it didn't work despite being returned in matches.
Is it even possible to dynamically create autofill?
It seems like the current autocomplete functionality does not allow for the editorParams to take a function as an argument to set the dropdown values. You can set it with an object of key/values if you can send that via AJAX, but as far as dynamically setting, altering, or searching the data, it seems like that's impossible to do at the moment.
The other option would be use the editor:"select", which can take a function to set its editorParams. It's not the best solution, but it's the one I had to go with at the moment.
There is an open issue on the Tabulator docs, but so far no response from the developers.
I wish I had a better answer for you!

Resources