1
votes

The mapping of database is this:

{
   "users": {
      "mappings": {
         "user": {
            "properties": {
              credentials": {
                  "type": "nested",
                  "properties": {
                     "achievement_id": {
                        "type": "string"
                     },
                     "percentage_completion": {
                        "type": "integer"
                     }
                  }
               },
               "current_location": {
                  "type": "geo_point"
               },
             "locations": {
               "type": "geo_point"
         }
            }
         }
      }
   }

Now In the mapping, You can see there are two geo-distance fields one is current_location and other is locations. Now I want to sort user based on credentials.percentage_completion which is a nested field. This work fine for example this query, Example Query:

GET /users/user/_search?size=23
{
  "sort": [
    {
      "credentials.percentage_completion": {
        "order": "desc",
        "missing": "_last"
      }
    },
 "_score"
  ],
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": {
        "geo_distance": {
          "distance": "100000000km",
          "user.locations": {
            "lat": 19.77,
            "lon": 73
          }
        }
      }
    }
  }
}

I want to change sorting order made into buckets, the desired order is first show all the people who are at 100KM radius of user.current_location and sort them according to credentials.percentage_completion and then rest of users sorted again by credentials.percentage_completion.

I tried putting conditional in sorting and made it multilevel but that will not work because only nested can have filters and that on nested fields child only.

I thought I can use _score for sorting and give more relevance to people who are under 1000 km but geo-distance is a filter, I don't seem to find any way to give relevance in filter.

Is there anything I am missing here , any help would be great.

Thanks

1

1 Answers

1
votes

Finally solved it, posting it here so other can also take some lead if they get here. The way to solve this is to give constant relevance score to particular query but as here it was Geo distance so was not able to use that in query, then I found Constant Score query: It allows to wrap a filter inside a query.

This is how query looks:

GET /users/user/_search?size=23
{
  "sort": [
    "_score",
    {
      "credentials.udacity_percentage_completion": {
        "order": "desc",
        "missing": "_last"
      }
    }
  ],
  "explain": true,
  "query": {
    "filtered": {
      "query": {
        "bool": {
          "should": [
            {
              "constant_score": {
                "filter": {
                  "geo_distance": {
                    "distance": "100km",
                    "user.current_location": {
                      "lat": 19.77,
                      "lon": 73
                    }
                  }
                },
                "boost": 50
              }
            },
            {
              "constant_score": {
                "filter": {
                  "geo_distance": {
                    "distance": "1000000km",
                    "user.locations": {
                      "lat": 19.77,
                      "lon": 73
                    }
                  }
                },
                "boost": 1
              }
            }
          ]
        }
      },
      "filter": {
        "geo_distance": {
          "distance": "10000km",
          "user.locations": {
            "lat": 19.77,
            "lon": 73
          }
        }
      }
    }
  }
}