Картография - ElasticSearch [7+] - PullRequest
1 голос
/ 09 мая 2019

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

Запрос консоли, который я собираюсь воссоздать с помощью 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)

1 Ответ

1 голос
/ 10 мая 2019

Для 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; }
}
...