J'ai un document

Comment faire un tri en utilisant un champ particulier sur elasticsearch

Ma requête est ci-dessous

{
   "sort":{
      "name":"desc"
   },
   "from":10,
   "size":149,
   "query":{
      "match_all":{
         
      }
   }
}

J'ai une erreur

Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [name] in order to load field data by uninverting the inverted index. Note that this can use significant memory.')\"}" }

Mon nom d'index est data_new

Ci-dessous le code à insérer dans l'index

test = [   {'id':1,'name': 'Cost Accounting 400', 'professor': ['Bill Cage', 'accounting']},
    { 'id':2,  'name': 'Computer Internals 250', 'professor': ['Gregg Payne', 'engineering']},
    {'id':3,   'name': 'Accounting Info Systems 350',   'professor': ['Bill Cage', 'accounting']},
    {'id':4,'name': 'Tax Accounting 200', 'professor': ['Thomas Baszo', 'finance']},
    {'id':5,'name': 'Capital Markets 350', 'professor': ['Thomas Baszo', 'finance']},
    {'id':6,'name': 'Theatre 410', 'professor': ['Sebastian Hern', 'art']},
    {'id':7,'name': 'Accounting 101', 'professor': ['Thomas Baszo', 'finance']},
    {'id':8,'name': 'Marketing 101', 'professor': ['William Smith', 'finance']},
    {'id':8,'name': 'Anthropology 230', 'professor': ['Devin Cranford', 'history']},
    {'id':10,   'name': 'Computer Science 101',
        'professor': ['Gregg Payne', 'engineering']}]
from elasticsearch import Elasticsearch
import json
es = Elasticsearch()
es.indices.create(index='data_new', ignore=400)
for e in test:
        es.index(index="data_new", body=e, id=e['id'])
search = es.search(index="data_new", body={"from" : 0, "size" : 2,"query": {"match_all": {}}})
search['hits']['hits']

Attendu

  • Ma première sortie attendue> Je dois trier la sortie par rapport à name uniquement

  • Deuxième sortie attendue> trier par rapport à name puis id

Comment faire la modification sur search = es.search(index="data_new", body={"from" : 0, "size" : 2,"query": {"match_all": {}}})

J'ai parcouru l'url https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-request-sort.html qui n'aide pas

0
Nons 7 oct. 2020 à 15:28

2 réponses

Meilleure réponse

Avant d'activer fielddata, demandez-vous pourquoi vous utilisez un champ de texte pour l'agrégation, le tri ou dans un script. Cela n'a généralement pas de sens de le faire.

Un champ de texte est analysé avant l'indexation afin qu'une valeur telle que New York puisse être trouvée en recherchant new ou york. Une agrégation de termes sur ce champ renverra un new bucket et un york bucket, alors que vous souhaitez probablement un seul bucket appelé New York

Au lieu de cela, vous devriez avoir un champ de texte pour les recherches en texte intégral et un champ de mot clé non analysé avec doc_values activé pour les agrégations, comme suit:

PUT data_new
{
  "mappings": {
    "properties": {
      "name": { 
        "type": "text",
        "fields": {
          "keyword": { 
            "type": "keyword"
          }
        }
      }
    }
  }
}

Je suppose que vous pouvez déjà traiter le nom comme un mot-clé en utilisant name.keyword comme ci-dessous,

GET /data_new/_search
{
  "sort" : [
     { "name.keyword" : {"order" : "asc"}}
  ],
 "from":10,
 "size":149,
 "query":{
   "match_all":{
     
     }
   }
}

Voir :

https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-request-sort.html

1
Always Sunny 7 oct. 2020 à 17:10

Vous pouvez faire une requête PUT sur l'index pour définir fielddata comme true:

curl --location --request PUT 'http://localhost:9200/index_name/info/_mapping' \
--header 'Content-Type: application/json' \
--data-raw '{
  "properties": {
     "desc": { 
       "type":     "text",
       "fielddata": true
     }
  }
}'

desc est le nom de la colonne

1
Yash 7 oct. 2020 à 12:44