ElasticSearch Color Search

For the color search on Pattern Design(a great platform for vector designs), I recently created a color search query powered by Elasticsearch. Try it, it works great.

In the schema mapping the average color is stored as an integer

averageColor {
	properties {
		red {
			type 'integer'
		green {
			type 'integer'
		blue {
			type 'integer'

For the query, we use a range query to get the images with the matching colors (plus/minus some tolerance). In order to get the best matches first, the scoring is (for simplicity) based on a Manhattan distance of the result color compared to the search color. The colorRange function ensures that the queried values lie within the rgb range. (the query string is constructed in php, thus the syntax)

	size: 100,
	query : {
		function_score: {
			filter : {
				and :
				 [ {
					"range" : {
						"averageColor.red" : {
							"gte":  '.colorRange($red - $tolerance).',
							"lte":  '.colorRange($red + $tolerance).'
					{"range" : {
					  "averageColor.green" :  {
						  "gte" :'.colorRange($green - $tolerance).',
						  "lte" : '.colorRange($green + $tolerance).'
					{"range" : {
					  "averageColor.blue" :  {
						  "gte" :'.colorRange($blue - $tolerance).',
						  "lte" : '.colorRange($blue + $tolerance).'
                script_score: {
                    "params": {
                        "red": '.$red.',
                        "green": '.$green.',
                        "blue": '.$blue.'
                    script: "-(abs(doc[\'averageColor.red\'].value - (double)red)+abs(doc[\'averageColor.green\'].value - green)+abs(doc[\'averageColor.blue\'].value - blue))"
This entry was posted in Software. Bookmark the permalink.

5 Responses to ElasticSearch Color Search

  1. Serg says:


    I have question about it.

    What value do you store in $tolerance and can you please provide example of colorRange() ?

    • Sti says:

      Hi Serg,

      we’re using 100 for tolerance (which is a pretty wide range, but is not a problem because the result is sorted by match)

      colorRange is actually only pseudocode in this context – it basically just clamps the value between 0 and 255. The implementation of colorRange looks like this:

              int max = 255
              int min = 0
              //if the value lies close to min or max so that the range would not be - tolerance to + tolerance
              //extent the range so that it has the full extent (otherwise queries on extreme values (like #fff would have a reduced range)
              if (tolerance < 0) {
                  if (value - tolerance > max) {
                      return max + 2 * tolerance
              if (tolerance > 0) {
                  if (value - tolerance < min) {
                      return min + 2 * tolerance
              return Math.max(min, Math.min(max, value + tolerance))
  2. sezin says:

    Hello there,

    How do you calculate a single rgb color from a whole image?

    • Sti says:

      By calculating the average of all colors (i.e. pixels) in the image. This is quite primitive and will not work well on images with many different colors (resulting in a muddy brown), but works well on images which have a overall tone or dominant color. The average is also what a human would see if she looked at it from far away.

Leave a Reply

Your email address will not be published. Required fields are marked *

Please solve this little equation for verifying that you\'re human *