Прекарах влудяващи няколко часа, опитвайки се да разбера как да създам заявка за търсене, която да направи това:

Връща всички документи, които имат низ на заявка навсякъде в което и да е поле, но само ако поле1 няма точна стойност1 ИЛИ поле2 има точна стойност2.

След твърде много време, опитвайки се да намеря добри обяснения или примери в документите и търсейки в StackOverflow, стигнах до това:

query: {
  bool: {
    minimum_should_match: 1,
    must: [{
      wildcard: {
       _all: { value: `*${querystring}*` }  
      }
    }],
    should: [{
      not: {
        term: { field1: value1 }
      }
    }, {
      term: { field2: value2 }
    }]
  }
}

Да, знам, че трябва да използвам стратегия nGram вместо заместващи знаци. Ще правя това в нашето приложение. Но тази публикация е за синтаксиса на заявката. И открих, че горното е абсурдно трудно да се сглоби.

Запазвайки нещата във формат JSON с цел преносимост, предлагам тази алтернатива:

query: [
  { _all: `*${querystring}*` },
  ‘AND’,
  [[ ‘NOT’, { field1: value1 } ], ‘OR’, { field2: value2 } ]
]

Освен че е по-лесно за разбиране, това е по-лесно за анализ:

  1. Обектите винаги ще имат ключ с име на поле (или специалното `_all`). Опциите за търсене в това поле могат да бъдат събрани под ключ `_options` или нещо друго в този обект.
  2. Заместващият знак се подразбира от наличието на * (буквалните звездички могат да бъдат екранирани).
  3. Членовете на низа на масива на заявката винаги са оператори.
  4. Вложените масиви са за групиране на оператори с полета и за определяне на приоритет.

Не е много красиво и честно казано не знам нищо за сложността на Elasticsearch, но може да се сериализира в JSON и е много по-просто.

Джед Верити е основател на Dataverse Consulting (скоро ще бъде Sentient Applications) и дългогодишен защитник на JavaScript, чиято работа става все по-лесна сега, когато езикът показва разпознаваеми признаци на зрялост.