im using Kibana and ES, i have an index with objects and an array called "reviews" that inside has properties called positive_comment, negative_comment, reviewer_name and more.
There are some reviews that have the field positive_comment empty (not null, just empty).
I need to order by the length of the field positive_comment first, so reviews with empty positive_comment comes last. The results are the same when ordering in SQL with LEN() property.
This is my query.
I also tried:
.value.size() in the script, or type "string" but no results.
{
"_source":[
"reviews.positive_comment"
],
"query":{
"bool":{
"filter":[
{
"term":{
"id":214
}
}
]
}
},
"sort":{
"_script":{
"script":"doc['reviews.positive_comment'].value.length()",
"type":"number",
"order":"asc"
}
}
}
This is my result:
{
"_source":{
"reviews":[
{
"positive_comment":"Great"
},
{
"positive_comment":"Really good product"
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":""
},
{
"positive_comment":"Awesome"
}
]
},
"sort":[
"0"
]
}
Elasticsearch doesn't support counting array elements, unless you use a script.
However, running a script for every matching document is going to degrade performance for every search query.
A better solution would be to count the values once, at index-time, and store the counts in dedicated fields (positive_comments_count, negative_comments_count, etc.) and use these fields for sorting.
Try following. It worked for me on ES 5.6.3. So, should work on higher versions too.
GET test/test/_search?filter_path=hits.hits
{
"query": {
"match_all": {}
},
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": "doc['reviews.positive_comment'].value.length()"
},
"order": "asc"
}
}
}
I have tested on ES 7.1 version too.
Mapping
PUT test
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"somefield": {
"type": "keyword"
},
"reviews": {
"properties": {
"positive_comment": {
"type": "keyword"
},
"item_id": {
"type": "double"
}
}
}
}
}
}
Query:
GET test/_search
{
"query": {
"match_all": {}
},
"_source": "reviews.positive_comment",
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": "doc['reviews.positive_comment'].value.length() % 100"
},
"order": "asc"
}
}
}
output
{
"hits" : {
"total" : {
"value" : 5,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "test5",
"_score" : null,
"_source" : {
"reviews" : [
{
"positive_comment" : ""
}
]
},
"sort" : [
0.0
]
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "test1",
"_score" : null,
"_source" : {
"reviews" : [
{
"positive_comment" : "Awesome"
}
]
},
"sort" : [
7.0
]
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "test3",
"_score" : null,
"_source" : {
"reviews" : [
{
"positive_comment" : "What a product"
}
]
},
"sort" : [
14.0
]
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "test2",
"_score" : null,
"_source" : {
"reviews" : [
{
"positive_comment" : "What a product.. amazing"
}
]
},
"sort" : [
24.0
]
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "test4",
"_score" : null,
"_source" : {
"reviews" : [
{
"positive_comment" : "Thats a great product.. "
}
]
},
"sort" : [
24.0
]
}
]
}
}
Am search my input keyword in multiple field using java api QueryBuilders.multiMatchQuery its not giving me exact results. Its giving some random results which is not relavant to my search query.
Please find my code below.
SearchRequest contentSearchRequest = new SearchRequest(ATTACHMENT);
SearchSourceBuilder contentSearchSourceBuilder = new SearchSourceBuilder();
contentSearchRequest.types(TYPE);
MultiMatchQueryBuilder attachmentQB = QueryBuilders.multiMatchQuery(keyword, "attachment.content","catalog_keywords","product_keywords");
contentSearchSourceBuilder.query(attachmentQB);
contentSearchSourceBuilder.size(5);
Please find my mapping details :
PUT document_attachment
{
"settings": {
"analysis": {
"analyzer": {
"custom_analyzer": {
"type": "custom",
"tokenizer": "whitespace",
"char_filter": [
"html_strip"
],
"filter": [
"lowercase",
"asciifolding"
]
},
"product_catalog_keywords_analyzer": {
"type": "custom",
"tokenizer": "whitespace",
"char_filter": [
"html_strip"
],
"filter": [
"lowercase",
"asciifolding"
]
}
}
}
},
"mappings" : {
"doc" : {
"properties" : {
"attachment" : {
"properties" : {
"content" : {
"type" : "text",
"analyzer": "custom_analyzer"
},
"content_length" : {
"type" : "long"
},
"content_type" : {
"type" : "text"
},
"language" : {
"type" : "text"
}
}
},
"fileContent" : {
"type" : "text"
},
"id": {
"type": "long"
},
"catalog_keywords" : {
"type" : "text",
"analyzer": "product_catalog_keywords_analyzer"
},
"product_keywords" : {
"type" : "text",
"analyzer": "product_catalog_keywords_analyzer"
},
}
}
}
}
I have simple Spring Boot application. My controller looks like this:
#RequestMapping(value = "/", method = RequestMethod.GET)
public List<Employee> getAllEmployees() {
return employeeRepository.findAll();
}
This code produce this json:
{
"_embedded" : {
"employees" : [ {
"firstName" : "firstName1",
"lastName" : "lastName1",
"_links" : {
"self" : {
"href" : "http://localhost:8080/employees/1"
},
"employee" : {
"href" : "http://localhost:8080/employees/1"
}
}
}, {
"firstName" : "firstName 1",
"lastName" : "lastName 1",
"_links" : {
"self" : {
"href" : "http://localhost:8080/employees/2"
},
"employee" : {
"href" : "http://localhost:8080/employees/2"
}
}
}, {
"firstName" : "firstName 3",
"lastName" : "lastName 3",
"_links" : {
"self" : {
"href" : "http://localhost:8080/employees/4"
},
"employee" : {
"href" : "http://localhost:8080/employees/4"
}
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/employees"
},
"profile" : {
"href" : "http://localhost:8080/profile/employees"
}
},
"page" : {
"size" : 20,
"totalElements" : 7,
"totalPages" : 1,
"number" : 0
}
}
But I need something like this:
[
{
"firstName" : "firstName1",
"lastName" : "lastName1",
},
{
"firstName" : "firstName2",
"lastName" : "lastName2",
},
]
The solution is removing spring-boot-starter-data-rest module.
I'm trying to bind the JSON data object retrieved from the servlet.
$("#mainVerticalMenu").kendoMenu({
dataSource : new kendo.data.DataSource({
transport: {
read: {
url: "net/samso/action/MenuAction?func_flag=getMenu&user_id=nexol", // the servlet url
dataType: "json",
}
},
schema: { // describe the result format
model : {
fields : {
text : {
type : "string"
},
value : {
type : "string"
},
subItemList: [{ // Sub item collection
text : {
type : "string"
},
value : {
type : "string"
}
}]
}
}
}
})
});
From the servlet, the JSON format is given as follows:
Hierarchy:
Text
Value
subItemList (ItemObject nested inside the menuitem)
- Text
- Value
Example JSON:
Which ends up looking like:
[{"text":"OuterMenu1","value":"menu1","subItemList":[{"text":"subMenuItem1","value":"subMenu1"},{"text":"subMenuItem2","value":"subMenu2"}]}]
Actual JSON I receive when calling the servlet directly:
[{"text":"Communication","value":"BASE_01","subItemList":[{"text":"상품소개조회","value":"BASE_01"},{"text":"공지사항","value":"BASE_02"},{"text":"의견수렴","value":"BASE_04"},{"text":"사용자관리","value":"BASE_05"},{"text":"받은쪽지","value":"BASE_07"},{"text":"보낸쪽지","value":"BASE_08"},{"text":"자유게시판","value":"BASE_09"},{"text":"매장/마진율 정보","value":"BASE_10"}]},{"text":"매입관리","value":"BUY_01","subItemList":[{"text":"입고/입고반품현황","value":"BUY_01"},{"text":"수평이동요청","value":"BUY_02"},{"text":"수평이동승인/조회","value":"BUY_03"}]},{"text":"판매관리","value":"SALE_01","subItemList":[{"text":"판매및반품등록","value":"SALE_01"},{"text":"판매및반품조회","value":"SALE_02"},{"text":"판매일보","value":"SALE_04"},{"text":"기간별판매현황","value":"SALE_05"},{"text":"판매순위분석","value":"SALE_06"},{"text":"판매순위표","value":"SALE_07"},{"text":"타사등록","value":"SALE_08"},{"text":"타사판매등록","value":"SALE_09"},{"text":"타사판매조회","value":"SALE_10"}]},{"text":"수불관리","value":"SUBUL_01","subItemList":[{"text":"상품주문등록","value":"SUBUL_01"},{"text":"상품주문조회","value":"SUBUL_02"},{"text":"미입고명세서","value":"SUBUL_10"},{"text":"일별수불현황","value":"SUBUL_04"},{"text":"재고현황","value":"SUBUL_05"},{"text":"수불 일/월보","value":"SUBUL_09"},{"text":"품목별수불현황","value":"SUBUL_08"},{"text":"재고조정","value":"SUBUL_11"},{"text":"타매장재고현황","value":"SUBUL_07"}]},{"text":"영업관리","value":"BUSS_01","subItemList":[{"text":"영업판매배치등록","value":"BUSS_01"},{"text":"영업판매조회","value":"BUSS_02"},{"text":"영업주문배치등록","value":"BUSS_03"},{"text":"영업주문조회","value":"BUSS_04"},{"text":"매장별 재고/수불현황","value":"BUSS_05"}]},{"text":"AS관리","value":"AS_01","subItemList":[{"text":"A/S의뢰 관리","value":"AS_01"}]},{"text":"관리자","value":"SUP_06","subItemList":[{"text":"기초코드관리","value":"SUP_06"},{"text":"시스템관리","value":"SUP_05"},{"text":"그룹관리","value":"SUP_02"},{"text":"그룹소속관리","value":"SUP_03"},{"text":"그룹권한관리","value":"SUP_04"},{"text":"매장등록현황","value":"SUP_01"},{"text":"마진율조회","value":"SUP_07"},{"text":"상품코드별권한등록","value":"SUP_08"},{"text":"거래처별상품권한등록","value":"SUP_09"},{"text":"마감현황","value":"SUP_10"},{"text":"SAP송수신기록조회","value":"SUP_12"}]},{"text":"회계","value":"ACCT_01","subItemList":[{"text":"WEB-POS 사용자현황","value":"ACCT_01"},{"text":"WEB-POS 입금등록","value":"ACCT_02"}]}]
I'd like to ask two questions:
The servlet is not being called at all, even though I've explicitly declared the transport URL in the datasource.
Is the above schema correct for declaring outer menu items and nesting items inside them?
The servlet is not being called because Kendo Menu does not define a DataSource for loading its content. BUT that doesn't mean that you cannot do it: yes, you can!
What you should do is:
Define an empty menu.
Define a DataSource.
Trigger manually a read in the DataSource
Append received data to the original menu.
The code:
var menu = $("#menu").kendoMenu({}).data("kendoMenu");
var ds = new kendo.data.DataSource({
transport: {
read: {
url : "menu.json",
dataType: "json"
}
},
schema : {
data: function (data) {
menu.append(data);
}
}
});
ds.read();
About your second question regarding the format of the JSON: replace subItemList by items, that's it. The entries on your JSON would look like:
[
{
"text" : "Communication",
"value" : "BASE_01",
"items": [
{
"text" : "상품소개조회",
"value": "BASE_01"
},
{
"text" : "공지사항",
"value": "BASE_02"
},
{
"text" : "의견수렴",
"value": "BASE_04"
},
{
"text" : "사용자관리",
"value": "BASE_05"
},
{
"text" : "받은쪽지",
"value": "BASE_07"
},
{
"text" : "보낸쪽지",
"value": "BASE_08"
},
{
"text" : "자유게시판",
"value": "BASE_09"
},
{
"text" : "매장/마진율 정보",
"value": "BASE_10"
}
]
},
{
"text" : "매입관리",
"value" : "BUY_01",
"items": [
{
"text" : "입고/입고반품현황",
"value": "BUY_01"
},
{
"text" : "수평이동요청",
"value": "BUY_02"
},
{
"text" : "수평이동승인/조회",
"value": "BUY_03"
}
]
},
{
"text" : "판매관리",
"value" : "SALE_01",
"items": [
{
"text" : "판매및반품등록",
"value": "SALE_01"
},
{
"text" : "판매및반품조회",
"value": "SALE_02"
},
{
"text" : "판매일보",
"value": "SALE_04"
},
{
"text" : "기간별판매현황",
"value": "SALE_05"
},
{
"text" : "판매순위분석",
"value": "SALE_06"
},
{
"text" : "판매순위표",
"value": "SALE_07"
},
{
"text" : "타사등록",
"value": "SALE_08"
},
{
"text" : "타사판매등록",
"value": "SALE_09"
},
{
"text" : "타사판매조회",
"value": "SALE_10"
}
]
},
{
"text" : "수불관리",
"value" : "SUBUL_01",
"items": [
{
"text" : "상품주문등록",
"value": "SUBUL_01"
},
{
"text" : "상품주문조회",
"value": "SUBUL_02"
},
{
"text" : "미입고명세서",
"value": "SUBUL_10"
},
{
"text" : "일별수불현황",
"value": "SUBUL_04"
},
{
"text" : "재고현황",
"value": "SUBUL_05"
},
{
"text" : "수불 일/월보",
"value": "SUBUL_09"
},
{
"text" : "품목별수불현황",
"value": "SUBUL_08"
},
{
"text" : "재고조정",
"value": "SUBUL_11"
},
{
"text" : "타매장재고현황",
"value": "SUBUL_07"
}
]
},
{
"text" : "영업관리",
"value" : "BUSS_01",
"items": [
{
"text" : "영업판매배치등록",
"value": "BUSS_01"
},
{
"text" : "영업판매조회",
"value": "BUSS_02"
},
{
"text" : "영업주문배치등록",
"value": "BUSS_03"
},
{
"text" : "영업주문조회",
"value": "BUSS_04"
},
{
"text" : "매장별 재고/수불현황",
"value": "BUSS_05"
}
]
},
{
"text" : "AS관리",
"value" : "AS_01",
"items": [
{
"text" : "A/S의뢰 관리",
"value": "AS_01"
}
]
},
{
"text" : "관리자",
"value" : "SUP_06",
"items": [
{
"text" : "기초코드관리",
"value": "SUP_06"
},
{
"text" : "시스템관리",
"value": "SUP_05"
},
{
"text" : "그룹관리",
"value": "SUP_02"
},
{
"text" : "그룹소속관리",
"value": "SUP_03"
},
{
"text" : "그룹권한관리",
"value": "SUP_04"
},
{
"text" : "매장등록현황",
"value": "SUP_01"
},
{
"text" : "마진율조회",
"value": "SUP_07"
},
{
"text" : "상품코드별권한등록",
"value": "SUP_08"
},
{
"text" : "거래처별상품권한등록",
"value": "SUP_09"
},
{
"text" : "마감현황",
"value": "SUP_10"
},
{
"text" : "SAP송수신기록조회",
"value": "SUP_12"
}
]
},
{
"text" : "회계",
"value" : "ACCT_01",
"items": [
{
"text" : "WEB-POS 사용자현황",
"value": "ACCT_01"
},
{
"text" : "WEB-POS 입금등록",
"value": "ACCT_02"
}
]
}
]