Как правильно создать индекс в ElasticSearch?

Для лучшего восприятия я взял совершенно другую тематику и переименовал поля

Пример:
"компании" : 
[{
   "название" : "значение",
   "hash" : "УникальноеЗначение",
   ...
   "работники" : [
         "должность" : ["ИмяРаботника", "ИмяРаботника", "ИмяРаботника"],
         "должность" : "ИмяРаботника",
         ...
         "должность" : "ИмяРаботника"
      ],
   "ключ" : "значение"
}, и т.д. идентичные предыдущему объекту объекты]

Всего существует 1000 различных должностей, однако это не значит, что все они будут в 1 компании. Во всех компаниях будет не более 15 должностей (данное ограничение не требует строгого определения, если это не повлияет на быстродействие). (Звучит немного глупо в данном контексте, но от этого нельзя избавиться)

и соответственно создание индексов, по которому и будут вопросы
client.indices.create({
	index: "компании",
	body: {
		"mappings": {
			"компания": {
				"properties": {
					"навание": {
						"type": "string"
					},
					"hash": {
						"type": "string"
					},
					...
					"работники": {
						???
					}
				}
			}
		}
	}
}, function (error, response) {
	var body = GetData();
	client.bulk({
		body: body
	}, function (err, resp) {
		res.render('index', {result: 'Indexing Completed!'});
	})
});


Собственно вопросы:
1) При добавлении новой компании должна быть проверка на существование аналогичной по полю "hash". Заменить все поля если такая компания уже существует. Если не существует, то добавить. Поле заранее сгененировано и не может быть изменено. Как это реализовать?
2) Как реализовать список работников при таком большом количестве различных ключей (т.е. должностей)?

Как я могу это сделать:
1) Просто удалять данные по полю "hash". В таком случае будет по ~10 удалений в секунду. Мне кажется, что это неправильный путь, который явно скажется на быстродействии (возможно я ошибаюсь и так и надо делать?).
2) Использовать что то вроде {"type": "string"} : {"type": "string"} (не работает, хотя я и не надеялся на работу подобного кода, однако проверка не заняла более 1 минуты).

PS в 99% случаев поиск будет производиться по работникам (возможно даже что по всем 15).
  • Вопрос задан
  • 7248 просмотров
Решения вопроса 1
onqu
@onqu
weasy
1. Проверять ничего не надо, если данные не нужны, запрос на обновление всего документа аналогичен запросу на добавление. Запрос ниже либо создаст новый документ, либо полностью заменит существующий.

PUT /компании/компания/{_id}
{
    "навание": "SpaceX",
    "работники":  ...,
}


Если "hash" уникален для каждой копании, его можно использовать в качестве _id

PUT /компании/компания/{hash}
{
    ...
}


В более ранних версиях (до 1.5) можно было использовать alias для поля _id, которое может генерироваться автоматически:

"mappings": {
    "компания": {
        // в текущей версии: 2.3 depricated - сказывалось на производительности
        "_id": {"path": "hash"},
        "properties": {
            "навание": {
                "type": "string"
            },
            ...
        }
    }
}


2. В эластике нет, как таковых массивов, есть вложенные объекты. Любое поле документа может содержать множество значений, но значения должны быть одного типа. Тип может быть nested или object, nested позволяет производить более удобный поиск при множестве вложенных объектов.

Если правильно понимаю, и должности разные, то будет удобнее использовать nested. Иначе object.

"mappings": {
    "компания": {
        "properties": {
            "работники": {
                "type": "nested",
                "properties": {
                    "должность": {
                        "type": "string"
                    },
                    "имя": {
                        "type": "string"
                    }
                }
            }
        }
    }
}

// создание/обновление
PUT /компании/компания/{_id}
{
    "название": "...",
    "hash": "...",
    "работники": [
        {
            "должность": "манагер",
            "имя": ["Анатолий", "Андрей"]
        },
        {
            "должность":  ["управляющий", "заместитель"]
            "имя": "Дмитрий"
        },
        {
            "должность": "кассир",
            "имя": ["Татьяна", "Анастасия"]
        },
    ]
}

// примерный поиск
GET /компании/компания/_search
{
    "query": {
        "nested": {
            "path": "работники",
            "query": {
                "bool": {
                    "must": [
                        { "match": { "работники.должность": "управляющий" }},
                        { "match": { "работники.должность":  "кассир" }} 
                    ]
                }
            }
        }
    }
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы