Фильтрация данных с помощью nodejs и elasticsearch

В настоящее время я столкнулся с проблемой, связанной с моей таблицей данных, реализованной в ReactJS. Я получаю данные из elasticsearch и заполняю ими данные. Процесс извлечения данных отлично работает без примененного фильтра, однако, когда я применяю фильтры к данным, таблица данных остается пустой, даже если в источнике данных есть соответствующие записи.

Структура параметров, которые я отправляю, выглядит следующим образом:

{
  pageIndex: 1,
  pageSize: 10,
  sort: { order: '', key: '' },
  query: '',
  filterData: {
    analysis: [ '0', '1', '2', '3' ],
    threat_level_id: [ '1', '2', '3', '4' ],
  }
}

Конечная точка:

POST /api/v1/events/public/список

Контроллер:

exports.getPublicEvents = async (req, res) => {
  try {
    client.ping()
    const { pageIndex, pageSize, sort, query, filterData } = req.body
    let esQuery = {
      index: 'ns_*',
      body: {
        query: {
          bool: {
            must: [
              {
                match_all: {},
              },
            ],
            filter: [],
          },
        },
        from: (pageIndex - 1) * pageSize,
        size: pageSize,
      },
    }
    if (query) {
      esQuery.body.query.bool.must = [
        {
          match: {
            'Event.info': {
              query: query,
              fuzziness: 'AUTO',
            },
          },
        },
      ]
    }
    if (filterData.analysis.length > 0) {
      esQuery.body.query.bool.filter.push({
        terms: {
          'Event.analysis': filterData.analysis,
        },
      })
    }
    if (filterData.threat_level_id.length > 0) {
      esQuery.body.query.bool.filter.push({
        terms: {
          'Event.threat_level_id': filterData.threat_level_id,
        },
      })
    }
    let esResponse = await client.search(esQuery)
    let data = esResponse.hits.hits.map((hit) => hit._source)
    let total = esResponse.hits.total.value

    res.status(200).json({
      status: 'success',
      data: data,
      total: total,
    })
  } catch (error) {
    res.status(500).json({
      error: 'Error connecting to Elasticsearch',
      errorMessage: error.message,
    })
  }
}

Контроллер ниже без фильтров и работает нормально.

exports.getPublicEvents = async (req, res) => {
  try {
    client.ping()
    const { pageIndex, pageSize, sort, query } = req.body
    let esQuery = {
      index: 'ns_*',
      body: {
        query: {
          match_all: {},
        },
        from: (pageIndex - 1) * pageSize,
        size: pageSize,
      },
    }
    if (query) {
      esQuery.body.query = {
        match: {
          'Event.info': {
            query: query,
            fuzziness: 'AUTO',
          },
        },
      }
    }
    let esResponse = await client.search(esQuery)
    let data = esResponse.hits.hits.map((hit) => hit._source)
    let total = esResponse.hits.total.value

    res.status(200).json({
      status: 'success',
      data: data,
      total: total,
    })
  } catch (error) {
    res.status(500).json({
      error: 'Error connecting to Elasticsearch',
      errorMessage: error.message,
    })
  }
}

Версия ElasticSearch: 7.17.8

Результат: console.info(JSON.stringify(esQuery))

{
  "index": "INDEX_NAME",
  "body": {
    "query": {
      "bool": {
        "must": [{ "match_all": {} }],
        "filter": [
          { "terms": { "Event.analysis": ["0", "1", "2"] } },
          { "terms": { "Event.threat_level_id": ["1", "2", "3", "4"] } }
        ]
      }
    },
    "from": 0,
    "size": 10
  }
}

Данные в схеме elasticsearch

{
    "@version": "1",
    "@timestamp": "2023-02-01T14:43:09.997Z",
    "Event": {
        "info": ".......................",
        
        "description": ".......................",
        "analysis": 0,
        "threat_level_id": "4",
        "created_at": 1516566351,
        "uuid": "5a64f74f0e543738c12bc973322",
        "updated_at": 1675262417
    }
}

Отображение индекса

{
    "index_patterns": ["INDEX_NAME"],
    "template": "TEMPLATE_NAME",
    "settings": {
      "number_of_replicas": 0,
      "index.mapping.nested_objects.limit": 10000000
      },
    "mappings": {
      "dynamic": false,
      "properties": {
          "@timestamp": {
          "type": "date"
        },
        "Event": {
          "type": "nested",
          "properties": {
            "date_occured": {
              "type": "date"
            },
            "threat_level_id": {
              "type": "integer"
            },
            "description": {
              "type": "text"
            },
            "is_shared": {
              "type": "boolean"
            },
            "analysis": {
              "type": "integer"
            },
            "uuid": {
              "type": "text"
            },
            "created_at": {
              "type": "date"
            },
            "info": {
              "type": "text"
            },
            "shared_with": {
                "type": "nested",
                 "properties": {
                  "_id": {
                    "type": "text"
                }
              }
            },
            "updated_at": {
              "type": "date"
            },
            "author": {
              "type": "text"
            },
            "Attributes": {
              "type": "nested",
              "properties": {
                "data": {
                  "type": "text"
                },
                "type": {
                  "type": "text"
                },
                "uuid": {
                  "type": "text"
                },
                "comment": {
                  "type": "text"
                },
                "category": {
                  "type": "text"
                },
                "value": {
                  "type": "text"
                },
                "timestamp": {
                  "type": "date"
                }
              }
            }, 
            "organisation": {
              "type": "nested",
              "properties": {
                "name": {
                  "type": "text"
                },
                "uuid": {
                  "type": "text"
                }
              }
            },
            "Tags": {
              "type": "nested",
              "properties": {
                "color": {
                  "type": "text"
                },
                "name": {
                  "type": "text"
                }
              }
            },
            "TLP": {
              "type": "nested",
              "properties": {
                "color": {
                  "type": "text"
                },
                "name": {
                  "type": "text"
                }
              }
            }
          }
        }  
      }
    }
  }
  

Какие значения вы отправляете query в свой контроллер? это первый фрагмент? У вас нет ошибок от es client ? Логи, которые мы могли бы проанализировать?

Paulo 31.01.2023 16:18

Параметры, которые я отправляю, упоминаются в моем вопросе, а возвращаемые данные пусты и не получают ошибок в клиенте es.

Richard Branson 01.02.2023 11:48

Можете ли вы распечатать запрос, который генерируется при применении фильтров? как JSON.stringify(esQuery). Также вы можете указать, какую версию клиента ES вы используете, потому что в последних версиях параметр body исчез, а query следует указывать на верхнем уровне?

Val 01.02.2023 13:05

Я обновил свой вопрос и добавил версию ES и результат JSON.stringify(esQuery)

Richard Branson 01.02.2023 17:38

@Val я также добавил схему данных в ES

Richard Branson 01.02.2023 17:43

Я вижу, что в ваших документах есть Event.threat_level, но в вашем запросе есть Event. threat_level_id

Val 01.02.2023 17:45

@Val неважно, что я только что изменил имя свойства

Richard Branson 01.02.2023 17:47

примечание: size/from выходит за пределы раздела body, который должен содержать только часть запроса

Val 01.02.2023 17:53

@Val Контроллер без фильтров отлично работает, используя from & size внутри тела!

Richard Branson 01.02.2023 17:56

Просто сказать, что это не соответствует договору, это может сработать, но они могут быть не приняты во внимание. В любом случае, это не проблема. Сколько обращений вы получаете, выполняя этот запрос непосредственно в Kibana Dev Tools?

Val 01.02.2023 17:59

И меня все еще беспокоит, что у вас было threat_level против threat_level_id, если вы копировали/вставляли свой документ непосредственно в SO

Val 01.02.2023 18:00

@Val Это была просто опечатка, и я обновил ее в вопросе. его id_уровня_угрозы

Richard Branson 01.02.2023 18:02

@Val, вы нашли что-нибудь, что может помочь мне решить эту проблему, сэр?

Richard Branson 06.02.2023 15:08

Вы не ответили на мой последний вопрос: сколько обращений вы получаете при выполнении этого запроса непосредственно в Kibana Dev Tools для того же индекса?

Val 06.02.2023 15:13

@Val Я получаю пустые хиты: «хиты»: { «всего»: { «значение»: 0, «отношение»: «экв» }, «max_score»: ноль, «хиты»: []}

Richard Branson 07.02.2023 11:52

Когда я удаляю часть фильтра, запрос работает нормально. "filter": [ { "terms": { "Event.analysis": ["0", "1", "2"] } }, { "terms": { "Event.threat_level_id": ["1", "2", "3", "4"] } } ]

Richard Branson 07.02.2023 11:53

Можете ли вы поделиться своим отображением индекса в своем вопросе?

Val 07.02.2023 13:23

@Val Я обновил свой вопрос и добавил отображение индекса

Richard Branson 07.02.2023 14:13

Спасибо, но обратите внимание, что я все еще вижу поле с именем threat_level, а не threat_level_id в вашем сопоставлении. Хотя добавил мой ответ

Val 07.02.2023 14:18

Не беспокойтесь об этом, потому что я обновил id_level_id до уровня угрозы в своем реальном сопоставлении.

Richard Branson 07.02.2023 16:17
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
20
141
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Event — это вложенное поле, поэтому вам нужно использовать вложенные запросы, например:

{
  "index": "INDEX_NAME",
  "body": {
    "query": {
      "bool": {
        "must": [{ "match_all": {} }],
        "filter": [
          {
            "nested": {
              "path": "Event",
              "query": {"terms": { "Event.analysis": ["0", "1", "2"] }}
            } 
          },
          {
            "nested": {
              "path": "Event",
              "query": {"terms": { "Event.threat_level_id": ["1", "2", "3", "4"] }}
            } 
          }
        ]
      }
    },
    "from": 0,
    "size": 10
  }
}

Спасибо, мистер @Val, за вашу помощь. Теперь работает :)

Richard Branson 07.02.2023 16:32

Другие вопросы по теме