Search on multiple values with jquery autocomplete - jquery-ui

Hi I'm trying to get the jQuery UI autocomplete widget to work so that it searches for matches from multiple attributes of my array but something does not work in my code.
For the moment
The idea it is if I type "coupe", response will be "Porsche, Audi, Mercedes". In the same way I will able to type '911' and receive as response "Porsche". Thanks for your help.
$(function() {
var cars =
[
{ "constructor" : "BMW",
"model": "Z3",
"type": "cabrio" },
{ "constructor" : "Porsche",
"model": "911",
"type": "coupe" },
{ "constructor" : "Audi",
"model": "A3",
"type": "coupe" },
{ "constructor" : "Mercedes",
"model": "SL500",
"type": "coupe" }
];
$("#quickFind").autocomplete({
source: function(request, response){
var matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
response( $.grep( cars, function( value ) {
return matcher.test(value.constructor) || matcher.test(value.model) || matcher.test(value.type);
}));
}
});
});

On each object of your cars array is missing the "label" and "value" options, take a look:
http://jsfiddle.net/DLLVw/77/
$(function() {
var cars =
[
{
"label" : "BMW - Z3 - cabrio",
"value" : "BMWZ3",
"constructor" : "BMW",
"model": "Z3",
"type": "cabrio" },
{
"label" : "Porsche - 911 - coupe",
"value" : "Porsche911",
"constructor" : "Porsche",
"model": "911",
"type": "coupe" },
{ "label" : "Audi - A3 - coupe",
"value" : "AudiA3",
"constructor" : "Audi",
"model": "A3",
"type": "coupe" },
{
"label" : "Mercedes - SL500 - coupe",
"value" : "mercedessl500",
"constructor" : "Mercedes",
"model": "SL500",
"type": "coupe" }
];
$("#quickFind").autocomplete({
source: function(request, response){
var matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" );
response( $.grep( cars, function( value ) {
return matcher.test(value['constructor']) || matcher.test(value.model) || matcher.test(value.type);
}));
}
});
});

Related

Elastic search - aggregation filter for product options

I have a products catalogue where every product is indexed as follows (queried from http://localhost:9200/products/_doc/1) as sample:
{
"_index": "products_20201202145032789",
"_type": "_doc",
"_id": "1",
"_version": 1,
"_seq_no": 0,
"_primary_term": 1,
"found": true,
"_source": {
"title": "Roncato Eglo",
"description": "Amazing LED light made of wood and description continues.",
"price": 3990,
"manufacturer": "Eglo",
"category": [
"Lights",
"Indoor lights"
],
"options": [
{
"title": "Mount type",
"value": "E27"
},
{
"title": "Number of bulps",
"value": "4"
},
{
"title": "Batteries included",
"value": "true"
},
{
"title": "Ligt temperature",
"value": "warm"
},
{
"title": "Material",
"value": "wood"
},
{
"title": "Voltage",
"value": "230"
}
]
}
}
Every option contains different value, so there are many Mount type values, Light temperature values, Material values, and so on.
How can I create an aggregation (filter) where I can let customers choose between various Mount Type options:
[ ] E27
[X] E14
[X] GU10
...
Or let them choose from different Material options displayed as checkboxes:
[X] Wood
[ ] Metal
[ ] Glass
...
I can handle it on frontend once the buckets are created. Creation of different buckets for these options is What I am struggling with.
I have succesfully created and displayed and using aggregations for Category, Manufacturer and other basic ones. Thes product options are stored in has_many_through relationships in database. I am using Rails + searchkick gem, but those allow me to create raw queries to elastic search.
The prerequisite for such aggregation is to have options field as nested.
Sample index mapping:
PUT test
{
"mappings": {
"properties": {
"title": {
"type": "keyword"
},
"options": {
"type": "nested",
"properties": {
"title": {
"type": "keyword"
},
"value": {
"type": "keyword"
}
}
}
}
}
}
Sample docs:
PUT test/_doc/1
{
"title": "Roncato Eglo",
"options": [
{
"title": "Mount type",
"value": "E27"
},
{
"title": "Material",
"value": "wood"
}
]
}
PUT test/_doc/2
{
"title": "Eglo",
"options": [
{
"title": "Mount type",
"value": "E27"
},
{
"title": "Material",
"value": "metal"
}
]
}
Assumption: For a given document a title under option appears only once. For e.g. there can exists only one nested document under option having title as Material.
Query for aggregation:
GET test/_search
{
"size": 0,
"aggs": {
"OPTION": {
"nested": {
"path": "options"
},
"aggs": {
"TITLE": {
"terms": {
"field": "options.title",
"size": 10
},
"aggs": {
"VALUES": {
"terms": {
"field": "options.value",
"size": 10
}
}
}
}
}
}
}
}
Response:
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"OPTION" : {
"doc_count" : 4,
"TITLE" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Material",
"doc_count" : 2,
"VALUES" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "metal",
"doc_count" : 1
},
{
"key" : "wood",
"doc_count" : 1
}
]
}
},
{
"key" : "Mount type",
"doc_count" : 2,
"VALUES" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "E27",
"doc_count" : 2
}
]
}
}
]
}
}
}
}

TFS 2017 Work item Extension not working

New to this TS scripting so a little help is requested,
I'm trying to create an extension that created a url from 4 work item fields.
example contribution:
{
"manifestVersion": 1,
"id": "tritech-tfsurl-control",
"version": "0.1.18",
"name": "tritech-tfsurl-control",
"scopes": [ "vso.work", "vso.work_write" ],
"description": "4 fields to a url",
"publisher": "TriTech-Software-Systems",
"icons": {
"default": "img/logo.png"
},
"targets": [
{
"id": "Microsoft.VisualStudio.Services"
}
],
"tags": [
"Work Item",
"Work Item control",
"Url",
"Url tfs server"
],
"content": {
"details": {
"path": "details.md"
}
},
"links": {
"home": {
"uri": "http://www.Tritech.com"
}
},
"branding": {
"color": "rgb(220, 235, 252)",
"theme": "light"
},
"files": [
{
"path": "img",
"addressable": true
},
{
"path": "index.html",
"addressable": true
}
],
"categories": [
"Plan and track"
],
"contributions": [
{
"id": "tfsurlcontrol-action",
"type": "ms.vss-work-web.work-item-form-control",
"description": "Work Item fields to create url from",
"targets": [
"ms.vss-work-web.work-item-form"
],
"properties": {
"name": "tfsurl-control",
"uri": "index.html",
"height": 90,
"inputs": [
{
"id": "PreviousTFSServer",
"description": "The TFS server url that has the work item.",
"type": "WorkItemField",
"properties": {
"workItemFieldTypes": [ "String" ]
},
"validation": {
"dataType": "String",
"isRequired": true
}
},
{
"id": "TFSCollection",
"description": "The original tfs collection name",
"type": "WorkItemField",
"properties": {
"workItemFieldTypes": [ "String" ]
},
"validation": {
"dataType": "String",
"isRequired": true
}
},
{
"id": "TfsTeamProject",
"description": "Original TFS project name",
"type": "WorkItemField",
"properties": {
"workItemFieldTypes": [ "String" ]
},
"validation": {
"dataType": "String",
"isRequired": true
}
},
{
"id": "TfsWorkItemId",
"description": "Original work item id",
"type": "WorkItemField" ,
"properties": {
"workItemFieldTypes": [ "Integer" ]
}
}
]
}
}
]
}
then in my App.ts file is this,
///<reference types="vss-web-extension-sdk" />
import { Controller } from "./control";
import * as ExtensionContracts from "TFS/WorkItemTracking/ExtensionContracts";
import { WorkItemFormService } from "TFS/WorkItemTracking/Services";
var control: Controller;
var provider = () => {
return {
onLoaded: (workItemLoadedArgs: ExtensionContracts.IWorkItemLoadedArgs) => {
control = new Controller();
}
}
};
VSS.register(VSS.getContribution().id, provider);
this is my Control.ts file,
`
private _initialize(): void {
this._inputs = VSS.getConfiguration().witInputs;
this._ServerFieldName = this._inputs["PreviousTFSServer"];
this._CollectionFieldName = this._inputs["TFSCollection"];
this._ProjectFieldName = this._inputs["TFSTeamProject"];
this._WorkItemIdFieldName = this._inputs["TfsWorkItemId"];
WitService.WorkItemFormService.getService().then(
(service) => {
Q.spread<any, any>(
[ service.getFieldValue(this._ServerFieldName),service.getFieldValue(this._CollectionFieldName),
service.getFieldValue(this._ProjectFieldName),service.getFieldValue(this._WorkItemIdFieldName)],
(server: string, collection: string, project:string, id: number) => {
this._view = new View(server,collection,project,id);
}, this._handleError
).then(null, this._handleError);
},
this._handleError);
}
private _handleError(error: string): void {
let errorView = new ErrorView(error);
}
}
`
Then I added a view.ts
export class View {
constructor(server: string, collection: string, project: string, id: number) {
// container div
if(server)
{
var Container = $("<div />");
var workItemUrl = $("<span></span>").text("Original work item");
var a = $("<a> </a>");
var url = 'server + "/" + collection + "/" + project + "/_workitemId?=" + String(id)'
a.attr("href", url );
a.attr("target", "_blank");
a.text("here.");
workItemUrl.append(a);
//$('body').empty().append(Container);
$(".events").append(workItemUrl);
}
}
}
<Input Id="PreviousTFSServer" Value="TriTech.Source.Server" />
<Input Id="TFSCollection" Value="TriTech.Source.Collection" />
<Input Id="TFSTeamProject" Value="TriTech.Source.Project" />
<Input Id="TfsWorkItemId" Value="TriTech.Source.Id" />
</Inputs>
</ControlContribution>
</Group>`
I started with the latest edition of the vsts-extension-ts-seed-simple-master package. Compiles and creates the extension but I'm not seeing any url or link.
What am I missing?
The WIT has been edited to use the extension.
Web debug shows it is being loaded,
{"id":"TriTech-Software-Systems.tritech-tfsurl-control.tritech-tfsurlcontrol-action","description":"Work Item fields to create url from","type":"ms.vss-work-web.work-item-form-control-group","targets":["ms.vss-work-web.work-item-form"],"properties":{"name":"tritech-tfsurl-control","uri":"index.html","height":90,"inputs":[{"id":"PreviousTFSServer","description":"The TFS server url that has the work item.","type":"WorkItemField","properties":{"workItemFieldTypes":["String"]},"validation":{"dataType":"String","isRequired":true}},{"id":"TFSCollection","description":"The original tfs collection name","type":"WorkItemField","properties":{"workItemFieldTypes":["String"]},"validation":{"dataType":"String","isRequired":true}},{"id":"TfsTeamProject","description":"Original TFS project name","type":"WorkItemField","properties":{"workItemFieldTypes":["String"]},"validation":{"dataType":"String","isRequired":true}},{"id":"TfsWorkItemId","description":"Original work item id","type":"WorkItemField","properties":{"workItemFieldTypes":["Integer"]}}],"::Attributes":16,"::Version":"0.1.20"}}
Thanks in advance.
I ended up using static values and got it working.
var Provider = () => {
this.ServerfieldName = "Source.Server";
this.CollectionfieldName = "Source.Collection";
this.ProjectfieldName = "Source.Project";
this.WorkItemIdfieldName = "Source.Id";
this._view = View;
return{
onLoaded: (WorkItemLoadedArgs: ExtensionContracts.IWorkItemLoadedArgs) => {
var deferred = Q.defer();
WorkItemFormService.getService().then(
(service) => {
Q.spread<any, any>(
[service.getFieldValue(this.ServerfieldName),service.getFieldValue(this.CollectionfieldName),
service.getFieldValue(this.ProjectfieldName),service.getFieldValue(this.WorkItemIdfieldName)],
(server: string, collection: string, project: string, workitemId: number) => {
var data =(`${server}/${collection}/${project}/_workitems#_a=edit&id=${workitemId}`);
if(server){
this._view = new View(data);
}
else{
$('body').empty().append("This is the original Work Item");
}
})
.catch(function (e) {deferred.reject(e)}
);
return deferred.promise; //.then(null);
}
)}
}
};
and used a view,
/// <reference path="../typings/index.d.ts" />
export class View {
constructor(public value:string) {
var Container = $("<div role='link'> </div>");
Container.addClass("Container");
Container.attr('tabindex', '0');
var rdiv = $("<div/>").addClass("rightDiv");
var ldiv = $("<div/>");
var help = $("<span></span>").text("Original Tfs work item ");
var a = $("<a> </a>");
a.attr("href", value);
a.attr("target", "_blank");
a.text("here.");
help.append(a);
ldiv.append(help);
Container.append(rdiv);
Container.append(ldiv);
$('body').empty().append(Container);
}
}

Send ajax request in PeriodSelector AMChart

I have this javascript code to draw an amchart stock, just the PeriodSelector part:
var periodSelectorAjax = new AmCharts.PeriodSelector();
periodSelectorAjax.periods = [
{period: "F1", label: "Phase 1"},
{period: "F2", label: "Phase 2"},
{period: "F3", label: "Phase 3"},
{period: "MAX", selected: true, label: "MAX"}
];
I need to intercept when user click on period to reload the graph, I see that I can do it with this, from here:
var chart = AmCharts.makeChart( "chartdiv", {
"type": "stock",
// ...
"periodSelector": {
"position": "left",
"periods": [ {
"period": "MM",
"selected": true,
"count": 1,
"label": "1 month"
}, {
"period": "YYYY",
"count": 1,
"label": "1 year"
}, {
"period": "YTD",
"label": "YTD"
}, {
"period": "MAX",
"label": "MAX"
} ],
"listeners": [ {
"event": "changed",
"method": function( event ) {
if ( event.predefinedPeriod !== undefined ) {
console.log( event.predefinedPeriod, event.count );
}
}
} ]
},
// ...
} );
But I don't know how to put the last listeners part and use it with my code.
thanks
You can either use the addListener method or just set the listeners array directly on your periodSelectorAjax variable.
addListener example:
periodSelectorAjax.addListener("changed", function(event) {
// your code here
});
listeners property example:
periodSelectorAjax.listeners = [{
"event": "changed",
"method": function(event) {
// ...
}
}]

Access property in JSON response

I'm looking to grab the image 'src' within this JSON response, but my trying has left me at a loose end. Any help would be brilliant.
My Model
def test
response = self.class.get("URLFORRESPONSE")
#elements = response.parsed_response["extractorData"]
#parsed = #elements.collect { |e| e['src'] }
end
JSON Response
{
"extractorData" : {
"url" : "http://testwebsite.com/",
"resourceId" : "409417ee21618b70d74b03231a793c2d7",
"data" : [ {
"group" : [ {
"image" : [ {
"src" : "test0.jpg"
} ]
}, {
"image" : [ {
"src" : "test1.jpg"
} ]
}, {
"image" : [ {
"src" : "test2.jpg"
} ]
}, {
"image" : [ {
"src" : "test3.jpg"
} ]
}, {
"image" : [ {
"src" : "test4.jpg"
} ]
}
Your JSON is invalid. It should be:
{
"extractorData": {
"url": "http://testwebsite.com/",
"resourceId": "409417ee21618b70d74b03231a793c2d7",
"data": [{
"group": [{
"image": [{
"src": "test0.jpg"
}]
}, {
"image": [{
"src": "test1.jpg"
}]
}, {
"image": [{
"src": "test2.jpg"
}]
}, {
"image": [{
"src": "test3.jpg"
}]
}, {
"image": [{
"src": "test4.jpg"
}]
}]
}]
}
}
To extract the src's:
#parsed = #elements['data'][0]['group'].map{| g | g['image'][0]['src'] }
I know this is ugly as hell but i hope this sugestion helps.
Since HTTParty.parsed_response returns a hash and assuming you're using ruby 2.3, you can do:
#elements = response.parsed_response["extractorData"]
#elements.dig('data').collect{|h| h.dig('group').collect{|h| h.dig('image').collect{|h| h.dig('src')}}}
see it:
h = {"extractorData"=>{"url"=>"http://testwebsite.com/", "resourceId"=>"409417ee21618b70d74b03231a793c2d7", "data"=>[{"group"=>[{"image"=>[{"src"=>"test0.jpg"}]}, {"image"=>[{"src"=>"test1.jpg"}]}, {"image"=>[{"src"=>"test2.jpg"}]}, {"image"=>[{"src"=>"test3.jpg"}]}, {"image"=>[{"src"=>"test4.jpg"}]}]}]}}
h.dig('extractorData', 'data').collect{|h| h.dig('group').collect{|h| h.dig('image').collect{|h| h.dig('src')}}}
=> [[["test0.jpg"], ["test1.jpg"], ["test2.jpg"], ["test3.jpg"], ["test4.jpg"]]]

How to write script(inline) in script_score including some custom logic with if conditions on doc[] element?

I am a novice with elastic search and while writing script_score I am facing parse exception saying 'expected field name but got [START_ARRAY]'
Here is the mapping:
PUT toadb
{
"mappings":{
"keywords":{
"properties":{
"Name":{"type":"string","analyzer": "simple"},
"Type":{"type":"string","index": "not_analyzed"},
"Id":{"type":"string","index": "not_analyzed"},
"Boosting Field":{"type" : "integer", "store" : "yes"}
}
},
"businesses":{
"properties": {
"Name":{"type":"string","analyzer": "simple"},
"Type":{"type":"string","index": "not_analyzed"},
"Id":{"type":"string","index": "not_analyzed"},
"Business_seq":{"type":"string","index": "not_analyzed"},
"Status":{"type":"string","index": "not_analyzed"},
"System_rating":{"type" : "integer", "store" : "yes"},
"System_rating_weight":{"type" : "integer", "store" : "yes"},
"Position":{ "type":"geo_point","lat_lon": true},
"Display Pic":{"type": "string","index": "not_analyzed"},
"Boosting Field":{"type" : "integer", "store" : "yes"}
}
}
}
}
Here is the query I am trying to execute:
GET /toadb/_search
{
"query":{
"function_score" : {
"query" : {
"multi_match" : {
"query": "Restaurant",
"fields": [ "Name"],"fuzziness":1
}},
"script_score":
{
"script":"if(doc['Status'] && doc['Status']=='A'){ _score+ (doc['Boosting Field'].value);}"
}
},
"size":10
}
}
Please provide sample examples if any (Already referred to elasticsearch documentation)
It looks like you have mistakenly placed the size option in your query. In your example, you have added it as a field next to the function_score query. Instead, it belongs as a sibling to the root query object.
Try this:
GET /toadb/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "Restaurant",
"fields": [
"Name"
],
"fuzziness": 1
}
},
"script_score": {
"script": "if(doc['Status'] && doc['Status']=='A'){ _score+ (doc['Boosting Field'].value);}"
}
}
},
"size": 10
}
Have a look at the documentation for the request body search.

Resources