How to project simple data set into to anonymous type of a different shape - linq

I have a simple set of data that I am having trouble figuring out how to create the projection I want using LINQ.
public class Score {
public string Name { get; set; }
public int Value { get; set; }
}
var scores = new List<Score> {
new Score { Name = "jesse", Value = 10 },
new Score { Name = "jesse", Value = 12 },
new Score { Name = "jesse", Value = 15 },
new Score { Name = "billy", Value = 5 },
new Score { Name = "billy", Value = 7 },
new Score { Name = "billy", Value = 20 },
new Score { Name = "colin", Value = 25 },
new Score { Name = "colin", Value = 13 },
new Score { Name = "colin", Value = 8 }
};
I need to project 'scores' into an anonymous type with the following structure.
{
series : [
{ name : "jesse", data : [10, 12, 15 ] },
{ name : "billy", data : [ 5, 7, 20 ] },
{ name : "colin", data : [25, 13, 8 ] }
]
}
Any help is appreciated.

var result = new {
series = from score in scores
group score.Value by score.Name into nameValues
select new
{
name = nameValues.Key,
data = nameValues
}
};

Does this match the structure you want?
var query = scores.GroupBy(s => s.Name);
var result = query.Select(q => new {
Name = q.Key,
Data = q.ToArray().Select(k => k.Value)
});
var anotherAnon = new {series = result.ToArray()};

Related

Return multiple results with index terraform

I currently have the below lists,
local.security_list =
[
{
ocid = security_list_id_1
name = subnet1
},
{
ocid = security_list_id_2
name = subnet1
},
{
ocid = security_list_id_3
name = subnet2
},
{
name = subnet2
ocid = security_list_id_4
},
]
var.vcn_security_lists = [
{
security_list_name = security_list_1
subnet_name = subnet1
},
{
security_list_name = security_list_2
subnet_name = subnet1
},
{
security_list_name = security_list_3
subnet_name = subnet2
}
]
I want to create the security lists using the var.vcn_security_lists list and then assign them to the subnet later on by using the subnet_name field. I have done this previously using the index() function as below, which loops through a subnet and pulls out the security list with the same subnet name. The problem is that this only returns one item - how can I return multiple from a list ?
subnet_security_list_ocid = [local.security_list[index(local.security_list.*.name,var.vcn_security_lists[index(var.vcn_security_lists.*.subnet_name,var.vcn_subnets[count.index].subnet_name)].security_list_name)].id]

Elasticsearch - NEST - Upsert

I have the following two classes
Entry
public class Entry
{
public Guid Id { get; set; }
public IEnumerable<Data> Data { get; set; }
}
EntryData
public class EntryData
{
public string Type { get; set; }
public object Data { get; set; }
}
I have a bunch of different applications that produces messages to a queue that I then consume in a separate application to store that data in elasticsearch.
Im using a CorrelationId for all the messages and I want to use this ID as the ID in elasticsearch.
So given the following data:
var id = Guid.Parse("1befd5b62b944b4aa600c85632159e11");
var entries = new List<Entry>
{
new Entry
{
Id = id,
Data = new List<EntryData>
{
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION1_Received"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION1_Validated"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION1_Published"
},
}
},
new Entry
{
Id = id,
Data = new List<EntryData>
{
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION2_Received"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION2_Validated"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION2_Published"
},
}
},
new Entry
{
Id = id,
Data = new List<EntryData>
{
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION3_Received"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION3_Validated"
},
new EntryData
{
Data = DateTime.UtcNow,
Type = "APPLICATION3_Published"
},
}
},
};
I want this to be saved as one entry in elasticsearch where ID == 1befd5b6-2b94-4b4a-a600-c85632159e11 and a data array that contains 9 elements.
Im struggling a bit with getting this to work, when trying the following:
var result = await _elasticClient.BulkAsync(x => x.Index("journal").UpdateMany(entries, (descriptor, entry) => {
descriptor.Doc(entry);
return descriptor.Upsert(entry);
}), cancellationToken);
But this is just overwriting whatever already exists in the data array and the count is 3 instead of 9 (only the Application3 entries are saved).
So, is it possible to do what I want to do? I never worked with elasticsearch before so it feels like maybe Im missing something simple here... :)
Managed to solve it like this:
var result = await _elasticClient.BulkAsync(x => x.Index("journal").UpdateMany(entries, (descriptor, entry) => {
var script = new InlineScript("ctx._source.data.addAll(params.data)")
{
Params = new Dictionary<string, object> {{"data", entry.Data}}
};
descriptor.Script(b => script);
return descriptor.Upsert(entry);
}), cancellationToken);

C# Linq how to use group by to get the desired output

I have the following classes
public class Product
{
public string PNo {get;set;}
public String GCode {get;set;}
public IList<Detail> Details {get;set;}
}
public class Detail{
public string Color {get;set;}
public string Size {get;set;}
}
And i have the data in an array as below
PNO GCode Color Size Amount
12345 GCC A L 1
12345 GCC V M 2
12345 GCC C S 3
12345 GCC D XL 4
12345 GCC E XS 5
How do i get the following output using groupby so that my output could like shown below
Expected output:
{
PNO: 12345,
GCode: GCC,
options:[
{Color:A, Size:L, Amount: 1},
{Color:V, Size:M, Amount: 2},
{Color:C, Size:S, Amount: 3},
{Color:D, Size:XL, Amount: 4},
{Color:E, Size:XS, Amount: 5}
]
}
Thanks
Given the contract you defined. I think below code snippet is OK to generate the JSON you want, I use anonymous object a lot, you can replace with you entity class.
products.GroupBy(product => new
{
product.PNo,
product.GCode
})
.Select(productGroup => new
{
productGroup.Key.PNo,
productGroup.Key.GCode,
options = productGroup.SelectMany(product => product.Details.Select(detail => new
{
detail.Color,
detail.Size,
detail.Amount
}))
});
Hope it helps.
This will get you that expected output:
Query Syntax:
var result = (from item in collection
group item by new { item.PNO, item.GCode } into grouping
select new Product
{
PNo = grouping.Key.PNO,
GCode = grouping.Key.GCode,
Details = grouping.Select(item => new Detail { Color = item.Color, Size = item.Size, Amount = item.Amount }).ToList()
}).ToList();
Method Syntax:
var result = collection.GroupBy(item => new { item.PNO, item.GCode })
.Select(grouping => new Product
{
PNo = grouping.Key.PNO,
GCode = grouping.Key.GCode,
Details = grouping.Select(item => new Detail { Color = item.Color, Size = item.Size, Amount = item.Amount }).ToList()
}).ToList();
Test Data:
List<dynamic> collection = new List<dynamic>()
{
new { PNO = "12345", GCode = "GCC", Color = "A", Size="L", Amount=1 },
new { PNO = "12345", GCode = "GCC", Color = "V", Size="M", Amount=2 },
new { PNO = "12345", GCode = "GCC", Color = "C", Size="S", Amount=3 },
new { PNO = "12345", GCode = "GCC", Color = "D", Size="XL", Amount=4 },
new { PNO = "12345", GCode = "GCC", Color = "E", Size="XS", Amount=5 },
};

ElasticSearch NEST library to retrieve certain fields

Trying to achieve following,
Retrieve articles that match given id and genre
Retrieve selected fields for matching records
I have tried this with Sense(chrome plugin),
POST /d3acampaign/article/_search
{
"fields": ["title","genre"] ,
"query": {
"filtered": {
"filter": {
"bool": {
"must": [{
"term": {
"id": "6"
}
},
{
"term": {
"genre": "metal"
}
}]
}
}
}
}
}
For C# code i am trying to build the query using following construct,
FilterContainer fc = null;
TermFilter title = new TermFilter()
{
Field = "id",
Value = "6",
};
TermFilter genre = new TermFilter()
{
Field = "genre",
Value = "metal",
};
fc = title & genre;
QueryContainer qc = new FilteredQuery() { Filter = fc };
var searchRequest = new SearchRequest
{
SearchType = Elasticsearch.Net.SearchType.QueryAndFetch,
Query = qc,
Indices = new IndexNameMarker[] {"journal"},
Types = new TypeNameMarker[] { "article" },
};
var r = client.SearchAsync<Article>(searchRequest);
var l = (List<Article>) r.Result.Documents;
I am able to run this query and get matching records, but i amnt sure how to specify selected fields to retrieve. Let me know what can be changed in C# code to specify necessary fields.
Thanks in advance.
Based on this answer you can modify your request object as follow:
var searchRequest = new SearchRequest
{
...
Fields = new List<PropertyPathMarker>
{
Property.Path<Article>(p => p.YourField)
}
};
or if you will decide to use source filtering:
var searchRequest = new SearchRequest
{
...
Source = new SourceFilter
{
Include = new []
{
Property.Path<Article>(p => p.YourField)
}
}
};
Hope it helps.

Not able to get TermVector results properly in SolrNet

I'm not able to get TermVector results properly thru SolrNet. I tried with the following code.
QueryOptions options = new QueryOptions()
{
OrderBy = new[] { new SortOrder("markupId", Order.ASC) },
TermVector = new TermVectorParameters
{
Fields = new[] { "text" },
Options = TermVectorParameterOptions.All
}
};
var results = SolrMarkupCore.Query(query, options);
foreach (var docVectorResult in results.TermVectorResults)
{
foreach (var vectorResult in docVectorResult.TermVector)
System.Diagnostics.Debug.Print(vectorResult.ToString());
}
In the above code, results.TermVectorResults in the outer foreach gives the proper count whereas docVectorResult.TermVector in the inner foreach is empty.
I've copied the generated solr query of the above code and issued against solr admin and I'm properly getting the termVectors values. The actual query I issued is below
http://localhost:8983/solr/select/?sort=markupId+asc&tv.tf=true&start=0&q=markupId:%2823%29&tv.offsets=true&tv=true&tv.positions=true&tv.fl=text&version=2.2&rows=50
First you should check HTTP query to sure termvector feature is set property.
If it's not OK, change your indexing based on:
The Term Vector Component
If it is OK,You can use "ExtraParams" by changing the handler to termvector handler. Try this:
public SolrQueryExecuter<Product> instance { get; private set; }
public ICollection<TermVectorDocumentResult> resultDoc(string q)
{
string SERVER="http://localhost:7080/solr/core";//change this
var container = ServiceLocator.Current as SolrNet.Utils.Container;
instance = new SolrQueryExecuter<Product>(
container.GetInstance<ISolrAbstractResponseParser<Product>>(),
new SolrConnection(SERVER),
container.GetInstance<ISolrQuerySerializer>(),
container.GetInstance<ISolrFacetQuerySerializer>(),
container.GetInstance<ISolrMoreLikeThisHandlerQueryResultsParser<Product>>());
instance.DefaultHandler = "/tvrh";
SolrQueryResults<Product> results =
instance.Execute(new SolrQuery(q),
new QueryOptions
{
Fields = new[] { "*" },
Start = 0,
Rows = 10,
ExtraParams = new Dictionary<string, string> {
{ "tv.tf", "false" },
{ "tv.df", "false" },
{ "tv.positions", "true" },
{ "tv", "true" },
{ "tv.offsets", "false" },
{ "tv.payloads", "true" },
{ "tv.fl", "message" },// change the field name here
}
}
);
return results.TermVectorResults;
}

Resources