Copy_to in Nest Attributes

You can't specify copy_to fields with attribute mapping because multiple fields can be specified, which are represented with the Fields type, and attribute parameters are restricted to constant values, so it's not possible to assign an instance of Fields within an [Attribute] declaration.

You can define copy_to fields with fluent mapping though. Since the original _source field is not modified, you don't need to add another property to your C# POCO for a copy_to field. Here's an example

client.CreateIndex("my-index", descriptor => descriptor
	.Mappings(ms => ms
		.Map<Project>(m => m
			.AutoMap()
			.Properties(p => p
				.Text(t => t
					.Name(n => n.ExternalCode)
					.Fields(f => f
						.Keyword(k => k
							.Name("keyword")
							.IgnoreAbove(256)
						)
					)
					.CopyTo(c => c
						.Field("another_field")
					)
				)
				.Object<Owner>(o => o
					.Name(n => n.Owner)
					.AutoMap()
					.Properties(pp => pp
						.Text(t => t
							.Name(n => n.FirstName)
							.Fields(f => f
								.Keyword(k => k
									.Name("keyword")
									.IgnoreAbove(256)
								)
							)
							.CopyTo(c => c
								.Field("another_field")
							)
						)
						.Text(t => t
							.Name(n => n.LastName)
							.Fields(f => f
								.Keyword(k => k
									.Name("keyword")
									.IgnoreAbove(256)
								)
							)
							.CopyTo(c => c
								.Field("another_field")
							)
						)
					)
				)
			)
		)
	)
	.Settings(s => s
		.Analysis(a => a
			.Analyzers(analyzer => analyzer
				.Custom("substring_analyzer", analyzerDescriptor => analyzerDescriptor
					.Tokenizer("keyword")
					.Filters("lowercase", "substring")
				)
			)
			.TokenFilters(tf => tf
				.NGram("substring", filterDescriptor => filterDescriptor
					.MinGram(1)
					.MaxGram(9)
				)
			)
		)
	)
);

Copy ExternalCode, Owner.FirstName and Owner,LastName to the "another_field" field. Now, if we index the following

client.IndexMany(new[] 
{
	new Project
	{
		Id = Guid.NewGuid(),
		ExternalCode = "foo",
	},
	new Project
	{
		Id = Guid.NewGuid(),
		Owner = new Owner
		{
			FirstName = "bar",
			LastName = "baz"		
		}
	}
}, "my-index");

client.Refresh("my-index");

We can search on the "another_field" field

client.Search<Project>(s => s
	.Index("my-index")
	.Query(q => q
		.Match(m => m
			.Field("another_field")
			.Query("foo bar baz")
		)
	)
);

which yields

{
  "took" : 64,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.51623213,
    "hits" : [
      {
        "_index" : "my-index",
        "_type" : "project",
        "_id" : "26b9cbf6-24b8-45d1-ae63-4b3061c2ecc3",
        "_score" : 0.51623213,
        "_source" : {
          "id" : "26b9cbf6-24b8-45d1-ae63-4b3061c2ecc3",
          "isOpen" : false,
          "isDeployed" : false,
          "owner" : {
            "firstName" : "bar",
            "lastName" : "baz"
          }
        }
      },
      {
        "_index" : "my-index",
        "_type" : "project",
        "_id" : "44aae698-10bf-4771-afc4-ac822c630e0d",
        "_score" : 0.2876821,
        "_source" : {
          "id" : "44aae698-10bf-4771-afc4-ac822c630e0d",
          "isOpen" : false,
          "isDeployed" : false,
          "externalCode" : "foo"
        }
      }
    ]
  }
}