Фильтровать документ по элементам в массиве ElasticSearch - PullRequest
0 голосов
/ 26 марта 2019

Я использую ElasticSearch для поиска по документам.Однако мне нужно убедиться, что текущий пользователь может видеть эти документы.Каждый документ связан с сообществом, в которое может входить пользователь.

Вот отображение для моего документа:

export const mapping = {
  properties: {
    amazonId: { type: 'text' },
    title: { type: 'text' },
    subtitle: { type: 'text' },
    description: { type: 'text' },
    createdAt: { type: 'date' },
    updatedAt: { type: 'date' },
    published: { type: 'boolean' },
    communities: { type: 'nested' }
  }
}

В настоящее время я сохраняю идентификаторы сообществ, которым принадлежит документ, в виде массива строк.Пример: ["edd05cd0-0a49-4676-86f4-2db913235371", "672916cf-ee32-4bed-a60f-9a7c08dba04b"]

В настоящее время, когда я фильтрую запрос с помощью {term: { communities: community.id } }, он возвращает все документы, независимо от сообществ, к которым он привязан.

Вот полный запрос:

{
  index: 'document',
  filter_path: { filter: {term: { communities: community.id } } },
  body: {
    sort: [{ createdAt: { order: 'asc' } }]
  }
}

Это следующий результат, основанный на идентификаторе сообщества "b7d28e7f-7534-406a-981e-ddf147b5015a". ПРИМЕЧАНИЕ: Это возвращение из моего graphql, поэтому сообщества в документе являются полными объектами после разрешения попаданий из запроса ES.

"hits": [
    {
      "title": "The One True Document",
      "communities": [
        {
          "id": "edd05cd0-0a49-4676-86f4-2db913235371"
        },
        {
          "id": "672916cf-ee32-4bed-a60f-9a7c08dba04b"
        }
      ]
    },
    {
      "title": "Boring Document 1",
      "communities": []
    },
    {
      "title": "Boring Document 2",
      "communities": []
    },
    {
      "title": "Unpublished",
      "communities": [
        {
          "id": "672916cf-ee32-4bed-a60f-9a7c08dba04b"
        }
       ]
    }
]

Когда я пытаюсь отобразить сообщества как {type: 'keyword', index: 'not_analyzed'}, я получаю сообщение об ошибке: [illegal_argument_exception] Could not convert [communities.index] to boolean.

Так что мне нужно изменить свое отображение, мой фильтр илии то и другое?Поиск по документам для 6,6 , я вижу, что terms требуется отображение non_analyzed.

ОБНОВЛЕНИЕ --------------------------

Я обновил сопоставление сообществбыть keyword как предложено ниже.Тем не менее, я все еще получил тот же результат.

Я обновил свой запрос следующим образом (используя идентификатор сообщества с документами):

query: { index: 'document',
  body: 
   { sort: [ { createdAt: { order: 'asc' } } ],
     from: 0,
     size: 5,
     query: 
      { bool: 
         { filter: 
            { term: { communities: '672916cf-ee32-4bed-a60f-9a7c08dba04b' } } } } } }

Что дает мне следующие результаты:

{
  "data": {
    "communities": [
      {
        "id": "672916cf-ee32-4bed-a60f-9a7c08dba04b",
        "feed": {
          "documents": {
            "hits": []
          }
        }
      }
    ]
  }
}

Похоже, чтомой фильтр работает слишком хорошо?

1 Ответ

1 голос
/ 27 марта 2019

Поскольку вы храните идентификаторы сообществ, убедитесь, что идентификаторы не анализируются. Для этого communities должно быть типа keyword. Во-вторых, вы хотите сохранить массив идентификаторов сообществ, поскольку пользователь может принадлежать нескольким сообществам. Для этого вам не нужно делать его типа nested. Вложенный имеет все вместе разные варианты использования. Для хранения значений в виде массива необходимо убедиться, что при индексации вы всегда передаете значения в поле в виде массива, даже если это одно значение.

Вам необходимо изменить отображение и способ индексации значений для поля communities.

1. Обновите отображение, как показано ниже:
PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "amazonId": {
          "type": "text"
        },
        "title": {
          "type": "text"
        },
        "subtitle": {
          "type": "text"
        },
        "description": {
          "type": "text"
        },
        "createdAt": {
          "type": "date"
        },
        "updatedAt": {
          "type": "date"
        },
        "published": {
          "type": "boolean"
        },
        "communities": {
          "type": "keyword"
        }
      }
    }
  }
}
2. Добавление документа в указатель:
PUT my_index/_doc/1
{
  "title": "The One True Document",
  "communities": [
    "edd05cd0-0a49-4676-86f4-2db913235371",
    "672916cf-ee32-4bed-a60f-9a7c08dba04b"
  ]
}
3. Фильтрация по идентификатору сообщества:
GET my_index/_doc/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "term": {
            "communities": "672916cf-ee32-4bed-a60f-9a7c08dba04b"
          }
        }
      ]
    }
  }
}

Подход с вложенным полем

1. Отображение:
PUT my_index_2
{
  "mappings": {
    "_doc": {
      "properties": {
        "amazonId": {
          "type": "text"
        },
        "title": {
          "type": "text"
        },
        "subtitle": {
          "type": "text"
        },
        "description": {
          "type": "text"
        },
        "createdAt": {
          "type": "date"
        },
        "updatedAt": {
          "type": "date"
        },
        "published": {
          "type": "boolean"
        },
        "communities": {
          "type": "nested"
        }
      }
    }
  }
}
2. Индексирование документа:
PUT my_index_2/_doc/1
{
  "title": "The One True Document",
  "communities": [
    {
      "id": "edd05cd0-0a49-4676-86f4-2db913235371"
    },
    {
      "id": "672916cf-ee32-4bed-a60f-9a7c08dba04b"
    }
  ]
}
3. Запрос (используется для вложенного запроса):
GET my_index_2/_doc/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "nested": {
            "path": "communities",
            "query": {
              "term": {
                "communities.id.keyword": "672916cf-ee32-4bed-a60f-9a7c08dba04b"
              }
            }
          }
        }
      ]
    }
  }
}

Возможно, вы заметили, что я использовал communities.id.keyword, а не communities.id. Чтобы понять причину этого, пройдите this .

...