# Which one is better schema?

**URL:** <https://discuss.elastic.co/t/which-one-is-better-schema/179164>\
**Category:** Elasticsearch\
**Created:** [May 1, 2019, 12:32am UTC](https://discuss.elastic.co/t/which-one-is-better-schema/179164 "2019-05-01T00:32:55Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Devon\_Yoo](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/devon_yoo/32/45284_2.png) [@Devon\_Yoo](https://discuss.elastic.co/u/Devon_Yoo)\
**Post date:** [May 1, 2019, 12:32am UTC](https://discuss.elastic.co/t/which-one-is-better-schema/179164/1 "2019-05-01T00:32:55Z")

</div>

I have two options for my Elasticsearch schema

Option 1.  
One data entry for an image. The key is image unique id and the value is a long string of entire list of numbers.

```auto
"visualwords" : {
    "image_id" : { "type" : "text", "store" : true },
    "numbers" : { "type" : "text", "store" : true }
}

```

Option 2.  
There will be around 970 entries per an image in average. Storing integer instead of string may reduce storage space it needs. Multiple data can be stored in bulk with a single query.

```auto
"visualwords" : {
    "image_id" : { "type" : "text", "store" : true },
    "number" : { "type" : "integer", "store" : true }
}

```

First of all, I have a bunch of image\_ids and each image id has about 970 vector numbers like 125, 156, 2303.

The use case is to get image\_id by searching by vectors. If [123, 124, 125] is an input, an image\_id which has the most matches should be returned.

I saw some people just put the entire numbers into a string with a space delimiter.  
And I can store the numbers as an integer for an entry like a traditional way.

I think each option has pros and cons in terms of search latency and storage space.  
How do you think about these options and what would you choose?

---

<div class="post-metadata">

**Author:** ![Mark\_Harwood](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/mark_harwood/32/10538_2.png) [@Mark\_Harwood](https://discuss.elastic.co/u/Mark_Harwood)\
**Post date:** [May 1, 2019, 11:29am UTC](https://discuss.elastic.co/t/which-one-is-better-schema/179164/2 "2019-05-01T11:29:01Z")

</div>

Numeric types in elasticsearch are optimised for range queries and unless you want to query for ranges of numbers e.g. "range 100 to 200" then it's probably not the right data structure.

If you map the data as a `keyword` field you'd need to supply the numbers in a JSON array to pass multiple values whereas with `text` field you'd need to use a single string and ensure the associated Analyzer used to parse the contents would break values up on whatever delimiter you use (whitespace or commas) and preserve all of the values eg keep numbers. The `keyword` type feels like the more natural option.

> The use case is to get image\_id by searching by vectors. If [123, 124, 125] is an input, an image\_id which has the most matches should be returned

Is IDF (rarity) of these terms important to you? If so, avoid the `terms` query which assumes all provided terms are of equal value and instead opt for a `bool` query with a `should` array of individual `term` queries.

---

<div class="post-metadata">

**Author:** ![Devon\_Yoo](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/devon_yoo/32/45284_2.png) [@Devon\_Yoo](https://discuss.elastic.co/u/Devon_Yoo)\
**Post date:** [May 1, 2019, 5:35pm UTC](https://discuss.elastic.co/t/which-one-is-better-schema/179164/3 "2019-05-01T17:35:51Z")

</div>

Thank you for your comment. But I am not very sure about the IDF part. First of all, please take a look at my queries below

```auto
curl -XPUT url/vectors -d '{
  "image_id":"P1",
  "words":"123 125 235 ... 10304 50305"}
}'

```

```auto
curl -XGET url/vectors -d '
{
  "query": {
    "bool": {
      "should": [
        { "match": { "words": "59796" } },
        { "match": { "words": "60928" } },
        { "match": { "words": "61027" } },
         ...
        { "match": { "words": "62161" } },
        { "match": { "words": "71747" } },
        { "match": { "words": "90993" } },
      ],
      "minimum_should_match": 30
    }
  },
  "_source": ["image_id"],
  "from": 0,
  "size": 10,
  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    }
  ]
}
'

```

As you might notice, I want to get a list of image\_ids in desc order if the image has more than 30 words that are matching the input words.

My query does what is supposed to do but I want to know if there's a better or more efficient way to get the results. And currently, the result list from my query has a lot of duplicates - if there is only one image\_id that meets the requirements, the return list is filled with the image\_id 30 times. Is there a way to reduce the duplicates?

Thanks!

---

<div class="post-metadata">

**Author:** ![Mark\_Harwood](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/mark_harwood/32/10538_2.png) [@Mark\_Harwood](https://discuss.elastic.co/u/Mark_Harwood)\
**Post date:** [May 2, 2019, 8:49am UTC](https://discuss.elastic.co/t/which-one-is-better-schema/179164/4 "2019-05-02T08:49:45Z")

</div>

> [@Devon\_Yoo](#):
>
> I am not very sure about the IDF part

It just means matches on some words can rank higher than others.  
In free text searches that would just mean a search for `aardvaark book` would score a document with the word `aardvaark` higher than a doc with just the word `book`.  
Rarer words score higher in text search but maybe in image search the inverse may be true. If your "word" token `372` actually represents a blue sky, that's likely to be a common word but actually important to score on.

> [@Devon\_Yoo](#):
>
> Is there a way to reduce the duplicates?

Do you want duplicates in your index to begin with?  
If not make your image\_id the choice of elasticsearch "\_id" field and it will ensure there's only ever one (like a primary key). The default is to autogenerate unique IDs on insertion.  
If for some reason you need duplicates then you can use the "field collapsing" feature to group results under the image\_id field

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [May 30, 2019, 8:49am UTC](https://discuss.elastic.co/t/which-one-is-better-schema/179164/5 "2019-05-30T08:49:46Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
