【问题标题】:C# Nest, Elastic Search: update and add to a field that is a listC# Nest,弹性搜索:更新并添加到作为列表的字段
【发布时间】:2016-03-18 16:47:11
【问题描述】:

这可能是一个愚蠢的问题,但我是弹性搜索和嵌套的新手。

我有课

Person
{
     public string Id {get; set;}
     public string Name {get; set;}
     public IList<string> PhoneNumbers {get; set;}
}

我想做的是通过添加来更新电话号码。

现在我用 2 个查询来做,但我想知道是否有办法用 1 来管理它。

        // See if the Person already exists
        var result = NestClient.Search<Person>(s => s
        .Index(_indexName)
        .Take(1)
        .Query(q => q
        .Term(p => p.Name, person.Name)
        && q.Term(p => p.Id, person.Id)));

        if (result.ServerError != null)
        { 
            throw result.OriginalException;

        }
        if (result.Documents.FirstOrDefault() == null)
        {
            var response = NestClient.Index<Person>(person);
            if (response.ServerError != null)
            {
                throw response.OriginalException;
            }
        }
        else
        {
            // If it does exist update and overwrite
            var savedPerson = result.Documents.First();

            IList<string> oldNums = SavedPerson.PhoneNumbers;
            IList<string> newNums = newPerson.PhoneNumbers;
            var combinedNums = oldNums.Concat(newNums);

            newPerson.PhoneNumbers = combinedNums.ToList<string>();

            var response = NestClient.Update(DocumentPath<Person>
                .Id(newPerson.Id),
                u => u.Doc(newPerson).DocAsUpsert(true));
            if (response.ServerError != null)
            {
                throw response.OriginalException;
            }
        }

基本上我希望我的 upsert 添加到现有的电话号码列表(如果存在)。

【问题讨论】:

  • 您打算保留重复的电话号码吗?如果不使用Union 而不是Concat

标签: c# elasticsearch nest


【解决方案1】:

如果脚本是一个选项,您可以使用scripted update 执行此操作。

在数组中更新后具有重复项的选项

var updateResponse = client.Update<Document, DocumentPartial>(DocumentPath<Document>.Id(1), descriptor => descriptor
    .Script(@"ctx._source.array += tab;")
    .Params(p => p.Add("tab", new[] {4, 5, 3})));

没有

var updateResponse = client.Update<Document, DocumentPartial>(DocumentPath<Document>.Id(1), descriptor => descriptor
    .Script(@"ctx._source.array += tab; ctx._source.array.unique();")
    .Params(p => p.Add("tab", new[] {4, 5, 3})));

完整示例:

public class DocumentPartial
{ 
    public int[] Array { get; set; }
}

public class Document
{
    public int Id { get; set; } 

    public int[] Array { get; set; }
}

var client = new ElasticClient(settings); 

client.CreateIndex(indexName, descriptor => descriptor
    .Mappings(map => map
        .Map<Document>(m => m.AutoMap()))); 

var items = new List<Document>
{
    new Document
    {
        Id = 1, 
        Array = new[] {1,2,3}
    } 
};

var bulkResponse = client.IndexMany(items);

client.Refresh(indexName);

var updateResponse = client.Update<Document, DocumentPartial>(DocumentPath<Document>.Id(1), descriptor => descriptor
    .Script(@"ctx._source.array += tab; ctx._source.array.unique();")
    .Params(p => p.Add("tab", new[] {4, 5, 3})));

希望对你有帮助。

【讨论】:

  • 有没有办法指定 unique() 适用于哪个字段属性...我的问题是当我使用上述脚本更新时,它会在我的嵌套文档中添加重复记录。 E..gg 我有 _id = 5 的记录,并且有一个嵌套文档,其中汽车作为卡 ID 和汽车名称,即使当我更新汽车名称时有汽车 ID = 1 和汽车名称 =“测试”的记录作为“test2”,它添加了另一条汽车 ID = 1 和汽车名称 =“test2”的记录。有没有办法避免这种情况..请帮助
  • 您可以编写自定义比较器以获得独特的功能,have a look
  • 谢谢 Rob.. 但再快一点。还有其他方法吗..我可以在上面的脚本中使用 for 循环,然后检查 if 条件,然后通过比较它们的 Id 来仅更新该文档..这可能吗?很抱歉提出问题,但我真的卡住了,无法继续..
  • 我觉得that的回答会对你有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-30
  • 2016-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多