How to display limited entity in AUI: Autocomplete search suggetion - liferay

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.

Related

How to find accounts with similar profile picture in twitter?

I am basically analyzing Twitter search results i.e activities on tweets (like, retweet, replies) to abstract unique interactors/users and comparing their profile picture with the expected PFP image. If the user profile image matches the comparison threshold, It is added to a collection.
Twitter search:
const searchResult: any = await axios.get(twitterBaseUrl + `/tweets/search/recent`, {
params: {
'query': searchKey,
'max_results': '10',
'tweet.fields': 'author_id,public_metrics,conversation_id'
},
headers: {
'Authorization': 'Bearer ' + twitterBearerToken,
}
});
find unique users interacting on tweets:
const uniqueUsers: any = [...new Map(users.map((user: any) => [user["id"], user])).values()];
Compare images:
for (const user of uniqueUsers) {
const compatibility = await commons.twitterService.compareImage(
pfpImage,
user.profile_image_url.replace('_normal', '')
);
// Compatibility threshold = 90%
if (compatibility > 90) {
usersWithDBPFP.push(user)
}
}
The problem with this approach is, it is hitting API rate limits and the accumulated result is way less than expected also I don't think this is a scalable solution.
In the meantime, I have found this awesome tool nftinspect which was quickly picking up and collecting Twitter profiles, I want to achieve a similar result, yet not clear in which direction I should go. Can you guys help me with this or suggest me any alternative ways, if you are comfortable? I would really appreciate that. Thank you :)

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.

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

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.

extjs search box

I'm, trying to add a search box exactly as one on sencha docs home page http://docs.sencha.com/ext-js/4-0/
I used the code from the example
http://docs.sencha.com/ext-js/4-0/#!/example/form/forum-search.html
and everything works as expected except for one thing ..
when I select an option from a list in my search box the combobox value is set to the selected value .. and when I press arrow down button it performs a new search with modified query ..
but I just want to see the results of the previous search - exactly the behaviour of the search box on sencha page
any ideas how to achieve that ?
After trying various things the code below does what i need, but maybe there is a better way ..
I had to set triggerAction to 'query' and also had to manually reset the text of the combobox in the the select event handler
var searchBox = {
xtype: 'combo',
store: dataStore,
displayField: 'title',
valueField: 'id',
autoSelect: false,
typeAhead: false,
fieldLabel: 'Search for',
hideTrigger:true,
anchor: '100%',
mode:'remote',
triggerAction: 'query',
listeners: {
'select' : function(combo) {
var selected = this.value;
combo.setValue(combo.lastQuery);
showResult(selected);
}
},
listConfig: {
loadingText: 'Searching ...',
emptyText: 'No matching posts found.',
getInnerTpl: function() {
return '<a class="search-item" href="?term={id}" onclick="return javascript:showResult(\'{id}\')">' +
'<h3><span>{title}<br /></span>{id}</h3></a>';
}
},
pageSize: 10
}
You need first sample from this page. Type "A" first
http://docs.sencha.com/ext-js/4-0/#!/example/form/combos.html

Sequelize select distinct rows

Is there a way to select distinct rows from a table using sequelize.js?
I looked through the documentation but the "finder methods" do not specify a way to accomplish this task.
Assuming you want to apply DISTINCT to the following query:
Tuple.findAll({attributes: ['key', 'value']});
then this is a (hackish) way to achieve what you want without having to write the whole query yourself:
Tuple.findAll({attributes: [[Sequelize.literal('DISTINCT `key`'), 'key'], 'value']});
(Tested with Sequelize v2.1.0)
Edit 2015-06-08: Still works with Sequelize v3.1.1
You can do the following:
myModel.findAll({
attributes: [[sequelize.fn('DISTINCT', sequelize.col('col_name')), 'alias_name']],
where:{}
}).then(data => {}).....
taken from issues and it works.
edit your "node_modules/sequelize/lib/dialects/mysql/query-generator.js"
at around line 118
change
var query = "SELECT <%= attributes %> FROM <%= table %>"
into
var query = "SELECT " + ((options.distinct)? 'DISTINCT ':'') +"<%= attributes %> FROM <%= table %>",
now you can add an option distinct: true in your sequelize request
hope it helps -_^
Model.findAll({Attributes: ['col_name1', 'col_name2'], group: ['col_name1', 'col_name2']});
it's perfectly fine with Sequelize 5.21
It's not possible automatically but if you don't mind creating the sql on your own, you could do this:
sequelize.query('sql goes here', null, { raw: plain }).success(function(data){
console.log(data)
})
Have fun :)
UPDATE
Sequelize now uses then instead of success as promise function.
Sequelize.query has been refactored to only use paramters sql and options
raw accepts true/false but no plain as value.
So, according to the new version, the code should look like this:
sequelize.query('sql goes here', { raw: true }).then(function(data){
console.log(data);
});
This is somewhat similar to the solution proposed by Pascal Ludwig, but for those landing here looking to get a list of distinct values for a given column, you can do the following:
MyModel.aggregate('teh_field', 'DISTINCT', { plain: false }).then(...)
// Resolves to: [ { DISTINCT: value1 }, { DISTINCT: value2 }, ... ]
With that, it's easy to transform it into a standard list:
MyModel.aggregate('teh_field', 'DISTINCT', { plain: false })
.map(function (row) { return row.DISTINCT })
.then(function (tehValueList) {
// tehValueList = [ value1, value2, ... ]
})
;
As of Sequelize version 1.7, the select query has been moved into lib/dialects/abstract/query-generator.js.
Around line 1167, change
mainQueryItems.push("SELECT "+mainAttributes.join ....)
to
mainQueryItems.push('SELECT ');
if (options.distinct) {
mainQueryItems.push('DISTINCT ');
}
mainQueryItems.push(mainAttributes.join(', ') + ' FROM ' + options.table);
By the way, I use Sqlite and Postgres, both of which support "DISTINCT". If you're using a dialect that doesn't support distinct, then obviously this line will cause problems for you, since it will be generated for all the SQL flavors that you're using. I suspect this is why this simple change hasn't made it into the main Sequelize source tree.

Resources