Сопоставление — ElasticSearch [7+]

Я решил большую часть этой проблемы, теперь мне интересно, в чем проблема и что я, возможно, делаю неправильно.

Консольный запрос, который я собираюсь воссоздать с помощью NEST:

    {
  "tdindex" : {
    "mappings" : {
      "documentModel" : {
        "properties" : {
          "accessControl" : {
            "type" : "boolean",
            "copy_to" : [
              "copyTo"
            ]
          },
          "comments" : {
            "properties" : {
              "comment" : {
                "type" : "text",
                 "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            },
                "copy_to" : [
                  "copyTo"
                ]},
              "createDate" : {
                "type" : "date",
 "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            },
                "copy_to" : [
                  "copyTo"
                ]},
              "user" : {
                "type" : "text",
                 "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            },
                "copy_to" : [
                  "copyTo"
                ]
              }
            }
          },
          "copyTo" : {
            "type" : "text"
          },
          "documentType" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            },
            "copy_to" : [
              "copyTo"
            ]
          },
          "filename" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            },
            "copy_to" : [
              "copyTo"
            ]
          },
          "folderID" : {
            "type" : "long",
            "copy_to" : [
              "copyTo"
            ]
          },
          "metadata" : {
            "properties" : {
              "key" : {
                "type" : "text",
                "fields" : {
                  "keyword" : {
                    "type" : "keyword",
                    "ignore_above" : 256
                  }
                },
                "copy_to" : [
                  "copyTo"
                ]
              },
              "value" : {
                "type" : "text",
                "fields" : {
                  "keyword" : {
                    "type" : "keyword",
                    "ignore_above" : 256
                  }
                },
                "copy_to" : [
                  "copyTo"
                ]
              }
            }
          },
          "uploadDate" : {
            "type" : "date",
            "copy_to" : [
              "copyTo"
            ]
          },
          "uploadUser" : {
            "type" : "text",
            "fields" : {
              "keyword" : {
                "type" : "keyword",
                "ignore_above" : 256
              }
            },
            "copy_to" : [
              "copyTo"
            ]
          }
        }
      }
    }
  }
}

В настоящее время у меня есть следующий консольный запрос, созданный в моем гнезде:

  {
  "mappings": {
    "properties": {
      "folderid": {
        "copy_to": [
          "CopyTo"
        ],
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "filename": {
        "copy_to": [
          "CopyTo"
        ],
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "documenttype": {
        "copy_to": [
          "CopyTo"
        ],
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "uploaddate": {
        "copy_to": [
          "CopyTo"
        ],
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "uploaduser": {
        "copy_to": [
          "CopyTo"
        ],
        "fields": {
          "keyword": {
            "ignore_above": 256,
            "type": "keyword"
          }
        },
        "type": "text"
      },
      "comments": {
        "properties": {
          "createdate": {
            "type": "date"
          },
          "comment": {
            "type": "text"
          },
          "user": {
            "type": "text"
          }
        },
        "copy_to": [
          "CopyTo"
        ],
        "type": "nested"
      },
      "metadata": {
        "properties": {
          "key": {
            "type": "text"
          },
          "value": {
            "type": "text"
          }
        },
        "copy_to": [
          "CopyTo"
        ],
        "type": "nested"
      },
      "CopyTo": {
        "type": "text"
      }
    }
  }
}

Как видите, DocumentModel не учитывается…

Я использую код NEST:

_elasticClient.CreateIndex(indexParameters.IndexName, c =>
            {
                c.Map<DocumentModel>(m => m

                   .Properties(ps => ps

                                      .Text(t => t.Name(n => n.FolderID).CopyTo(n => n.Field(f => f.CopyTo)).Fields(fd => fd.Keyword(k => k.Name("keyword").IgnoreAbove(256))))
                      .Text(t => t.Name(n => n.Filename).CopyTo(n => n.Field(f => f.CopyTo)).Fields(fd => fd.Keyword(k => k.Name("keyword").IgnoreAbove(256))))
                      .Text(t => t.Name(n => n.DocumentType).CopyTo(n => n.Field(f => f.CopyTo)).Fields(fd => fd.Keyword(k => k.Name("keyword").IgnoreAbove(256))))
                      .Text(t => t.Name(n => n.UploadDate).CopyTo(n => n.Field(f => f.CopyTo)).Fields(fd => fd.Keyword(k => k.Name("keyword").IgnoreAbove(256))))
                      .Text(t => t.Name(n => n.uploadUser).CopyTo(n => n.Field(f => f.CopyTo)).Fields(fd => fd.Keyword(k => k.Name("keyword").IgnoreAbove(256))))
                      .Nested<Comments>(cm => cm.Name(n => n.Comments).AutoMap().CopyTo(n => n.Field(f => f.CopyTo)))
                      .Nested<Metadata>(md => md.Name(n => n.Metadata).AutoMap().CopyTo(n => n.Field(f => f.CopyTo)))
                      .Text(t => t.Name(n => n.CopyTo)))

Моя DocumentModel выглядит так (я не могу использовать [ElasticsearchType(Name = "documentModel")] по какой-то причине в модели, не уверен, является ли это частью причины проблемы?):

public class DocumentModel
{
    [Text(Name = "filename")]
    public string Filename { get; set; }
    [Text(Name = "folderid")]
    public int FolderID { get; set; }
    [Text(Name = "uploaduser")]
    public string uploadUser { get; set; }
    [Date(Format = "MMddyyyy")]
    public DateTime UploadDate { get; set; }
    [Text(Name = "documenttype")]
    public string DocumentType { get; set; }
    [Boolean(NullValue = false)]
    public bool AccessControl { get; set; }
    [Nested]
    public List<Comments> Comments { get; set; }
    [Nested]
    public List<Metadata> Metadata { get; set; }
    [Text(Name = "CopyTo")]
    public string CopyTo { get; set; }


}

public class Comments
{
    [Date(Format = "MMddyyyy")]
    public DateTime CreateDate { get; set; }
    [Text(Name = "comment")]
    public string Comment { get; set; }
    [Text(Name = "user")]
    public string User { get; set; }
}

public class Metadata
{
    [Text(Name = "key")]
    public string Key { get; set; }
    [Text(Name = "value")]
    public string Value { get; set; }
}

Ошибка, которую я получаю из консоли при выполнении запроса:

{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "Root mapping definition has unsupported parameters:  [metadata : {copy_to=[CopyTo], type=nested, properties = {value = {type=text}, key = {type=text}}}] [filename : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [comments : {copy_to=[CopyTo], type=nested, properties = {createdate = {type=date}, comment = {type=text}, user = {type=text}}}] [uploaddate : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [CopyTo : {type=text}] [documenttype : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [folderid : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [uploaduser : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}]"
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "Failed to parse mapping [properties]: Root mapping definition has unsupported parameters:  [metadata : {copy_to=[CopyTo], type=nested, properties = {value = {type=text}, key = {type=text}}}] [filename : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [comments : {copy_to=[CopyTo], type=nested, properties = {createdate = {type=date}, comment = {type=text}, user = {type=text}}}] [uploaddate : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [CopyTo : {type=text}] [documenttype : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [folderid : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [uploaduser : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}]",
    "caused_by": {
      "type": "mapper_parsing_exception",
      "reason": "Root mapping definition has unsupported parameters:  [metadata : {copy_to=[CopyTo], type=nested, properties = {value = {type=text}, key = {type=text}}}] [filename : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [comments : {copy_to=[CopyTo], type=nested, properties = {createdate = {type=date}, comment = {type=text}, user = {type=text}}}] [uploaddate : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [CopyTo : {type=text}] [documenttype : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [folderid : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}] [uploaduser : {copy_to=[CopyTo], fields = {keyword = {ignore_above=256, type=keyword}}, type=text}]"
    }
  },
  "status": 400

Есть идеи?

Я предполагаю, что проблема связана с картой?

P.S. Я использую Kibana 6.7.1 и Elastic 6.7.1 через локальный хост. Я запускаю запрос (из объекта JSON, созданного запросом с использованием NEST)

Какую версию Nest вы используете? Текущая версия еще не поддерживает Elastic 7, но доступна альфа-версия, если вы включите предварительные версии в Nuget. Вы можете увидеть поддерживаемые версии здесь: github.com/elastic/elasticsearch-net

Joe Zack 09.05.2019 20:27

Оказывается, я использую NEST 7.0.0-aplha... Мне удалось приблизить консольный запрос к тому, что я хочу, но все равно без радости... Я обязательно обновлю этот пост, если добьюсь каких-либо успехов ... Ваше здоровье

Ollie Beumkes 09.05.2019 20:42

Пожалуйста, не меняйте полностью текст вопроса после того, как найдете решение, так как вы удаляете контекст исходного вопроса.

Backgammon 09.05.2019 22:11

Я не хотел менять весь контекст. Я понял, что проблема не была конкретно рассмотрена в вопросе, и когда я отправил вопрос, я понял, что структура запроса, который я ранее разместил, была неправильной, правильный код выше делает вопрос проще, почему я получаю mapper_parsing_exception, и если я не могу использовать [ElasticsearchType(Name = "documentModel")] - это что-то, что связано с проблемой синтаксического анализа и отсутствием documentModel... если вы видели оба вопроса, зачем публиковать то, что у вас есть, никому не поможет... не пишите, если вы не можете помочь решить проблему...

Ollie Beumkes 09.05.2019 22:19

Что касается отсутствующего ключа «documentModel»: ES 7.0 по умолчанию запрещает указывать тип документа, присваивая параметру запроса include_type_name значение false по умолчанию. См. elastic.co/guide/en/elasticsearch/reference/master/…. Ваша фактическая проблема, вероятно, связана с тем, как вы передаете сопоставление в Elasticsearch. Вам нужно быть более точным в том, что вы подразумеваете под «ошибкой, которую я получаю из консоли при выполнении запроса» - какую консоль? Какая конечная точка? Как вы выполняете запрос?

Backgammon 09.05.2019 22:33

Я только что попробовал это на своем кластере; сопоставление, сгенерированное для вас гнездом, на самом деле правильное и создает индекс, как и ожидалось. Взгляните на примеры в elastic.co/guide/en/elasticsearch/reference/current/… и elastic.co/guide/en/elasticsearch/reference/current/…, чтобы увидеть, как вы должны отправить запрос в ES. Есть небольшая вероятность, что это гнездовой жук. re: «не публикуйте сообщения, если вы не можете помочь решить проблему»: в качестве взаимного ответа не задавайте вопрос на StackOverflow, если вы не готовы внести свой вклад в развитие сайта.

Backgammon 09.05.2019 22:38

Cheers @Backgammon Я попробую еще раз и обновлю свой пост утром; что касается дальнейшего объяснения «Ошибка, которую я получаю из консоли при выполнении запроса», я запускаю Kibana 6.7.1 и Elastic 6.7.1 через локальный хост. Я запускаю запрос (из объекта JSON, созданного запросом с использованием NEST)… Как вы сказали, синтаксис кажется приемлемым (завтра мне нужно будет более внимательно посмотреть)

Ollie Beumkes 09.05.2019 23:18

Глядя на ваш код (конкретно я не знаком с NEST), похоже, что вы пропускаете вызов Mappings перед Map? См., например. пример вызова createIndex на этой странице: astic.co/guide/en/elasticsearch/client/net-api/current/…

Backgammon 09.05.2019 23:20

@Backgammon Я думаю, что в NEST 7.x (Elastic) он устарел, Nest теперь заявляет, что «CreateIndexDescriptor.Mapings (Func<MappingsDescriptor, <ITypeMapping>)» устарел: «Mapping больше не является словарем в 7.x, пожалуйста, используйте упрощенная карта ()…» было больно найти новый синтаксис

Ollie Beumkes 10.05.2019 00:20
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
9
2 201
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Для Elasticsearch 6.7.1 используйте последний клиент NEST 6.x, который на данный момент 6.7.0. Основные версии клиента совместимы с основными версиями Elasticsearch.

В NEST 6.7.0 сопоставление будет выглядеть примерно так:

private static void Main()
{
    var defaultIndex = "tdindex";
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

    var settings = new ConnectionSettings(pool)
        .DefaultIndex(defaultIndex);

    var client = new ElasticClient(settings);

    var visitor = new MyVisitor();  

    client.CreateIndex(defaultIndex, c => c
        .Mappings(m => m
            .Map<DocumentModel>(mm => mm
                .AutoMap(visitor)
                .Properties(ps => ps
                    .Nested<Comments>(cm => cm
                        .Name(n => n.Comments)
                        .AutoMap(visitor)
                    )
                    .Nested<Metadata>(md => md
                        .Name(n => n.Metadata)
                        .AutoMap(visitor)
                    )
                    .Text(t => t.Name(n => n.CopyTo))
                )
            )
        )
    );

}

public class MyVisitor : NoopPropertyVisitor
{
    public override void Visit(ITextProperty property, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute)
    {
        base.Visit(property, propertyInfo, attribute);
        property.CopyTo = Infer.Fields<DocumentModel>(f => f.CopyTo);
        property.Fields = new Properties
        {
            { "keyword", new KeywordProperty { IgnoreAbove = 256  } }
        };
    }
}

[ElasticsearchType(Name = "documentModel")]
public class DocumentModel
{
    [Text(Name = "filename")]
    public string Filename { get; set; }
    [Text(Name = "folderid")]
    public int FolderID { get; set; }
    [Text(Name = "uploaduser")]
    public string uploadUser { get; set; }
    [Date(Format = "MMddyyyy")]
    public DateTime UploadDate { get; set; }
    [Text(Name = "documenttype")]
    public string DocumentType { get; set; }
    [Boolean(NullValue = false)]
    public bool AccessControl { get; set; }
    [Nested]
    public List<Comments> Comments { get; set; }
    [Nested]
    public List<Metadata> Metadata { get; set; }
    [Text(Name = "copyTo")]
    public string CopyTo { get; set; }
}

public class Comments
{
    [Date(Format = "MMddyyyy")]
    public DateTime CreateDate { get; set; }
    [Text(Name = "comment")]
    public string Comment { get; set; }
    [Text(Name = "user")]
    public string User { get; set; }
}

public class Metadata
{
    [Text(Name = "key")]
    public string Key { get; set; }
    [Text(Name = "value")]
    public string Value { get; set; }
}

Поскольку все сопоставления текста, кроме свойства CopyTo, имеют ключевое слово multi_fields и copy_to для копирования в поле CopyTo, проще всего использовать определить это с посетителем. Сначала вызывается Automap(), минуя посетителя. Автоматическое сопоставление подберет сопоставления атрибутов моделей, а методы посещения посетителя позволят нам переопределить любой из них. Затем Properties() переопределит любые сопоставления из процесса автоматического сопоставления.

Окончательное выходное отображение

PUT http://localhost:9200/tdindex?pretty=true 
{
  "mappings": {
    "documentModel": {
      "properties": {
        "filename": {
          "type": "text",
          "copy_to": [
            "copyTo"
          ],
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "folderid": {
          "type": "text",
          "copy_to": [
            "copyTo"
          ],
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "uploaduser": {
          "type": "text",
          "copy_to": [
            "copyTo"
          ],
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "uploadDate": {
          "type": "date",
          "format": "MMddyyyy"
        },
        "documenttype": {
          "type": "text",
          "copy_to": [
            "copyTo"
          ],
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "accessControl": {
          "type": "boolean",
          "null_value": false
        },
        "comments": {
          "type": "nested",
          "properties": {
            "createDate": {
              "type": "date",
              "format": "MMddyyyy"
            },
            "comment": {
              "type": "text",
              "copy_to": [
                "copyTo"
              ],
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "user": {
              "type": "text",
              "copy_to": [
                "copyTo"
              ],
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        },
        "metadata": {
          "type": "nested",
          "properties": {
            "key": {
              "type": "text",
              "copy_to": [
                "copyTo"
              ],
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "value": {
              "type": "text",
              "copy_to": [
                "copyTo"
              ],
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
          }
        },
        "copyTo": {
          "type": "text"
        }
      }
    }
  }
}

Синтаксис NEST 7.x, совместимый с Elasticsearch 7.x, такой же; есть несколько вещей, которые устарели, чтобы изменить могу, чтобы удалить предупреждения, но синтаксис 6.x работает как есть

client.CreateIndex(defaultIndex, c => c
    // remove .Mappings()
    .Map<DocumentModel>(mm => mm
        .AutoMap(visitor)
        .Properties(ps => ps
            .Nested<Comments>(cm => cm
                .Name(n => n.Comments)
                .AutoMap(visitor)
            )
            .Nested<Metadata>(md => md
                .Name(n => n.Metadata)
                .AutoMap(visitor)
            )
            .Text(t => t.Name(n => n.CopyTo))
        )
    )
);

// Use RelationName instead of Name
[ElasticsearchType(RelationName = "documentModel")]
public class DocumentModel
{
    [Text(Name = "filename")]
    public string Filename { get; set; }
    [Text(Name = "folderid")]
    public int FolderID { get; set; }
    [Text(Name = "uploaduser")]
    public string uploadUser { get; set; }
    [Date(Format = "MMddyyyy")]
    public DateTime UploadDate { get; set; }
    [Text(Name = "documenttype")]
    public string DocumentType { get; set; }
    [Boolean(NullValue = false)]
    public bool AccessControl { get; set; }
    [Nested]
    public List<Comments> Comments { get; set; }
    [Nested]
    public List<Metadata> Metadata { get; set; }
    [Text(Name = "copyTo")]
    public string CopyTo { get; set; }
}

Это именно то, что мне нужно, проблема, как и в случае с моим кодом выше (в котором я не уверен, что все это прояснил...), заключается в том, что [ElasticsearchType(Name = "documentModel")] показывает ошибку: "Тип или пространство имен «Имя» не найдено».... Я не уверен, связано ли это с использованием NEST 7.0-alpha... Какую версию NEST вы используете?

Ollie Beumkes 10.05.2019 00:16

Я использую 6.7.0. Это будет связано с использованием версии 7.0.0-alpha1, которая несовместима с Elasticsearch 6.7.0.

Russ Cam 10.05.2019 00:18

Я попытаюсь понизить рейтинг своего NEST, я быстро вернусь с результатом

Ollie Beumkes 10.05.2019 00:21

С NEST 6.7.0 код вашего решения и мой работают; при этом я хотел бы увидеть синтаксис для 7.x, если кто-нибудь его знает? На данный момент я буду придерживаться 6.7.0 и реализую класс посетителей, приветствую этого Расса, если кто-то не ответит мне с синтаксисом 7.x в ближайшее время, я дам вам ответ.

Ollie Beumkes 10.05.2019 00:35

тот же синтаксис будет работать в 7.x. Есть несколько устаревших предупреждений, для исправления которых можно изменить код.

Russ Cam 10.05.2019 00:58

когда я использую [ElasticsearchType(Name = "documentModel")], он показывает ошибку: "Не удалось найти тип или пространство имен "Имя"". .0.

Ollie Beumkes 10.05.2019 11:18

Если вы используете Elasticsearch 7.x, попробуйте 7.0.0-alpha2. Name был добавлен обратно, но устарел: github.com/elastic/elasticsearch-net/pull/3702

Russ Cam 10.05.2019 12:19

Я использовал ваш автомаппер с объектом посетителя, собираюсь использовать 6.7.0, пока 7.0 не выйдет за пределы альфа-ура

Ollie Beumkes 11.05.2019 00:51

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