简体   繁体   中英

Elasticsearch : How to retrieve only the desired nested objects

I have the below mapping structure for my Elasticsearch index.

{
  "users": {
    "mappings": {
      "user-type": {
        "properties": {
          "lastModifiedBy": {
            "type": "string"
          },
          "lastModifiedDate": {
            "type": "date",
            "format": "dateOptionalTime"
          },
          "details": {
            "type": "nested",
            "properties": {
              "lastModifiedBy": {
                "type": "string"
              },
              "lastModifiedDate": {
                "type": "date",
                "format": "dateOptionalTime"
              },
              "views": {
                "type": "nested",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "properties": {
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "type": {
                        "type": "string"
                      },
                      "value": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Basically I want to retrieve ONLY the view object inside details based on index id & view id(details.views.id).

I have tried with the below java code.But seems to be not working.

SearchRequestBuilder srq =  this.client.prepareSearch(this.indexName)
    .setTypes(this.type)
    .setQuery(QueryBuilders.termQuery("_id", sid))
    .setPostFilter(FilterBuilders.nestedFilter("details.views", 
         FilterBuilders.termFilter("details.views.id", id)));

Below is the query structure for this java code.

{
  "query": {
    "term": {
      "_id": "123"
    }
  },
  "post_filter": {
    "nested": {
      "filter": {
        "term": {
          "details.views.id": "def"
        }
      },
      "path": "details.views"
    }
  }
}

Since details is nested and view is nested inside details , you basically need two nested filters as well (one for each level) + the constraint on the _id field is best done with the ids query . The query DSL would look like this:

{
  "query": {
    "ids": {
      "values": [
        "123"
      ]
    }
  },
  "post_filter": {
    "nested": {
      "filter": {
        "nested": {
          "path": "details.view",
          "filter": {
            "term": {
              "details.views.id": "def"
            }
          }
        }
      },
      "path": "details"
    }
  }
}

Translating this into Java code yields:

// 2nd-level nested filter
FilterBuilder detailsView = FilterBuilders.nestedFilter("details.views", 
    FilterBuilders.termFilter("details.views.id", id));

// 1st-level nested filter
FilterBuilder details = FilterBuilders.nestedFilter("details", detailsView);

// ids constraint
IdsQueryBuilder ids = QueryBuilders.idsQuery(this.type).addIds("123");

SearchRequestBuilder srq =  this.client.prepareSearch(this.indexName)
   .setTypes(this.type)
   .setQuery(ids)
   .setPostFilter(details);

PS: I second what @Paul said, ie always play around with the query DSL first and when you know you have zeroed in on the exact query you need, then you can translate it to the Java form.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM