2017-03-14 31 views
1

我在ElasticSearch索引中有一个列表。如何使用NEST 2将新元素添加到列表中?我已经搜索了我的问题的答案,但是我发现的所有内容都是answer for the version 1.x,它不适用于我。ElasticSearch - 使用NEST 5.x添加嵌套列表中的元素<T>

MODEL:

public class TicketModel 
{ 
    public Guid Id { get; set; } 
    public Guid IdUser { get; set; } 
    public Guid IdAuthor { get; set; } 
    public Guid? IdAssignedUser { get; set; } 
    public Guid? IdAsset { get; set; } 
    public Guid? IdOwner { get; set; } 
    public DateTime CreationDate { get; set; } 
    public DateTime? ClosingDate { get; set; } 
    public DateTime? DueDate { get; set; } 
    public DateTime? LastDateUserView { get; set; } 
    public DateTime? LastDateAssignedUserView { get; set; } 
    public string TicketCode { get; set; } 
    public string Title { get; set; } 
    public int IdCategory { get; set; } 
    public int? IdSubcategory { get; set; } 
    public short? IdPriority { get; set; } 
    public short IdState { get; set; } 
    public bool IsNew { get; set; } 

    public List<TicketMessageModel> TicketMessageList { get; set; } 
} 

public class TicketMessageModel 
{ 
    public Guid Id { get; set; } 
    public Guid IdTicket { get; set; } 
    public Guid IdUserFrom { get; set; } 
    public Guid? IdUserTo { get; set; } 
    public DateTime? CreationDate { get; set; } 
    public DateTime? DeleteDate { get; set; } 
    public string Message { get; set; } 
    public bool HideToFinalUser { get; set; } 
    public byte? MessageType { get; set; } 

    public List<TicketMessageFilesModel> MessageFileList { get; set; } 
} 

public class TicketMessageFilesModel 
{ 
    public Guid Id { get; set; } 
    public Guid? IdTicketMessage { get; set; } 
    public string FileName { get; set; } 
    public string FileTitle { get; set; } 
    public string FileOriginalName { get; set; } 
    public byte FileType { get; set; } 
} 

我试图找到出路使用其他的答案,但我得到了困在这里:

client.Update<ElasticSearchTickets.TicketMessageModel, object>(new DocumentPath<ElasticSearchTickets.TicketMessageModel>(elem.Id), 
       q => q.Script(x => x.Inline("ctx._source.MessageFileList += elem"))./*??*/); 

在此先感谢。

编辑:

这里是我试图插入我的名单里面一个新的元素代码:

ElasticSearchTickets.TicketMessageModel elem = new ElasticSearchTickets.TicketMessageModel() 
      { 
       CreationDate = message.CreationDate, 
       DeleteDate = message.DeleteDate, 
       HideToFinalUser = message.HideToFinalUser, 
       Id = message.Id, 
       IdTicket = message.IdTicket, 
       IdUserFrom = message.IdUserFrom, 
       IdUserTo = message.IdUserTo, 
       Message = message.Message, 
       MessageType = message.MessageType, 
       MessageFileList = tempList 
      }; 
      var response = client.Update<ElasticSearchTickets.TicketModel, object>(new DocumentPath<ElasticSearchTickets.TicketModel>(elem.IdTicket.ToString()), q => q 
       .Script(s => s 
        .Inline("if (ctx._source.TicketMessageList == null) { ctx._source.TicketMessageList = element; } else { ctx._source.TicketMessageList += element; }") 
        .Params(d => d.Add("element", new [] { elem })) 
       )); 

但现在我有一个服务器错误,因为属性“元”有不被宣布。如何解决这个问题?

这里是映射:

"mappings": { 
    "ticket": { 
    "properties": { 
     "ClosingDate": { 
     "type": "date" 
     }, 
     "CreationDate": { 
     "type": "date" 
     }, 
     "DueDate": { 
     "type": "date" 
     }, 
     "Id": { 
     "type": "keyword" 
     }, 
     "IdAsset": { 
     "type": "keyword" 
     }, 
     "IdAssignedUser": { 
     "type": "keyword" 
     }, 
     "IdAuthor": { 
     "type": "keyword" 
     }, 
     "IdCategory": { 
     "type": "integer" 
     }, 
     "IdOwner": { 
     "type": "keyword" 
     }, 
     "IdPriority": { 
     "type": "short" 
     }, 
     "IdState": { 
     "type": "short" 
     }, 
     "IdSubcategory": { 
     "type": "integer" 
     }, 
     "IdUser": { 
     "type": "keyword" 
     }, 
     "IsNew": { 
     "type": "boolean" 
     }, 
     "LastDateAssignedUserView": { 
     "type": "date" 
     }, 
     "LastDateUserView": { 
     "type": "date" 
     }, 
     "TicketCode": { 
     "type": "text", 
     "fields": { 
      "keyword": { 
      "type": "keyword", 
      "ignore_above": 256 
      } 
     } 
     }, 
     "TicketMessageList": { 
     "type": "nested", 
     "properties": { 
      "CreationDate": { 
      "type": "date" 
      }, 
      "DeleteDate": { 
      "type": "date" 
      }, 
      "HideToFinalUser": { 
      "type": "boolean" 
      }, 
      "Id": { 
      "type": "keyword" 
      }, 
      "IdTicket": { 
      "type": "keyword" 
      }, 
      "IdUserFrom": { 
      "type": "keyword" 
      }, 
      "IdUserTo": { 
      "type": "keyword" 
      }, 
      "Message": { 
      "type": "text", 
      "fields": { 
       "keyword": { 
       "type": "keyword", 
       "ignore_above": 256 
       } 
      } 
      }, 
      "MessageFileList": { 
      "properties": { 
       "FileName": { 
       "type": "text", 
       "fields": { 
        "keyword": { 
        "type": "keyword", 
        "ignore_above": 256 
        } 
       } 
       }, 
       "FileOriginalName": { 
       "type": "text", 
       "fields": { 
        "keyword": { 
        "type": "keyword", 
        "ignore_above": 256 
        } 
       } 
       }, 
       "FileTitle": { 
       "type": "text", 
       "fields": { 
        "keyword": { 
        "type": "keyword", 
        "ignore_above": 256 
        } 
       } 
       }, 
       "FileType": { 
       "type": "short" 
       }, 
       "Id": { 
       "type": "keyword" 
       }, 
       "IdTicketMessage": { 
       "type": "keyword" 
       } 
      } 
      }, 
      "MessageType": { 
      "type": "short" 
      } 
     } 
     }, 
     "Title": { 
     "type": "text", 
     "fields": { 
      "keyword": { 
      "type": "keyword", 
      "ignore_above": 256 
      } 
     } 
     } 
    } 
+0

映射是什么样的? “TicketMessageList”是映射为“对象”类型还是“嵌套”类型? –

+0

另外,MessageFileList的映射 –

+0

@RussCam TicketMessageList是一个嵌套类型,MessageFileList是一个对象。 –

回答

1

这里有一个剥离下来的例子

void Main() 
{ 
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200")); 
    var defaultIndex = "default-index"; 
    var connectionSettings = new ConnectionSettings(pool) 
      .DefaultIndex(defaultIndex); 

    var client = new ElasticClient(connectionSettings); 

    if (client.IndexExists(defaultIndex).Exists) 
     client.DeleteIndex(defaultIndex); 

    client.CreateIndex(defaultIndex, c => c 
     .Mappings(ms => ms 
      .Map<TicketMessageModel>(m => m 
       .AutoMap() 
       .Properties(p => p 
        .Nested<TicketMessageFilesModel>(n => n 
         .Name(nn => nn.MessageFileList) 
         .AutoMap() 
        ) 
       ) 
      ) 
     ) 
    ); 

    var id = "ticketmessage"; 

    client.Index(new TicketMessageModel 
    { 
     Id = id, 
     MessageFileList = new List<UserQuery.TicketMessageFilesModel> 
     { 
      new TicketMessageFilesModel { Id = "file1" } 
     } 
    }); 

    client.Update<TicketMessageModel, object>(id, q => q 
     .Script("if (ctx._source.messageFileList == null) { ctx._source.messageFileList = elem; } else { ctx._source.messageFileList += elem; }") 
     .Params(d => d 
      .Add("elem", new[] { new TicketMessageFilesModel { Id = "file2" } }) 
     ) 
    ); 

    var getResponse = client.Get<TicketMessageModel>(id); 
} 

public class TicketMessageModel 
{ 
    public string Id { get; set; } 
    public List<TicketMessageFilesModel> MessageFileList { get; set; } 
} 

public class TicketMessageFilesModel 
{ 
    public string Id { get; set; } 
} 

getResponse JSON响应

{ 
    "_index" : "default-index", 
    "_type" : "ticketmessagemodel", 
    "_id" : "ticketmessage", 
    "_version" : 2, 
    "found" : true, 
    "_source" : { 
    "id" : "ticketmessage", 
    "messageFileList" : [ { 
     "id" : "file1" 
    }, { 
     "id" : "file2" 
    } ] 
    } 
} 

关注几点:

  1. 您需要处理的情况下,可能没有任何项目通过检查列表中是否为空
  2. 为了追加到列表中,您需要将您希望追加的项目包装到数组中,例如列表和数组可以附加在一起。
  3. 您需要使用序列化字段名称,因为它们存在于_source中。默认情况下,NEST骆驼案件在序列化到Elasticsearch字段名时POCO属性名

编辑:

它看起来像您正在使用针对Elasticsearch 5.x的NEST 5.x的工作; 5.x中的默认脚本语言是Painless,与2.x中的Groovy相反,因此脚本中必须存在一些细微的差异。

这里是与无痛

client.Update<TicketMessageModel, object>(id, q => q 
    .Script(s => s 
     .Inline("if (ctx._source.messageFileList == null) { ctx._source.messageFileList = new ArrayList(); } ctx._source.messageFileList.add(params.elem);") 
     .Params(d => d 
      .Add("elem", new TicketMessageFilesModel { Id = "file2" }) 
     ) 
    ) 
); 

退房的guide on Painless的更多详细信息5.x的兼容版本。您还可以使用使用Groovy最初的例子太多,通过指定.Lang("groovy").Script()里面,但你也需要让内联Groovy脚本中加入

script.engine.groovy.inline: true 

到Elasticsearch.yml配置来运行。Groovy scripts are disabled by default for security reasons.

+0

看看我的回答,你的代码似乎有效,但它不承认我的财产。我已更新我的问题 –

+0

@FrancescoRoggia您需要将示例适应您的用例;有两件事我可以看到,可能会导致问题:1.脚本中有一个Pascal封装属性名称 - 参见上面的第3点和2.看起来您使用的是NEST 5.x而不是NEST 2.x - NEST 5.x只与Elasticsearch 5.x兼容。你能提供关于服务器错误的更多细节吗? –

+0

{类型:illegal_argument_exception原因:“无法执行脚本”CausedBy:“类型:script_exception原因:”编译错误“CausedBy:”类型:illegal_argument_exception原因:“未定义变量[元素]。”“”}问题出在Params,因为我更新_source里面的正确元素,但代码不能识别我的参数 –

相关问题