I have a schema like below:
public class Company
{
public string Name { get; set; }
public List<User> Users { get; set; }
}
public class User
{
public string UserName { get; set; }
public List<Role> Roles { get; set; }
}
public class Role
{
public string RoleName { get; set; }
//other properties
}
Now I want to build a string which contains comma-separated roles and separated by pipe for each user.
For example, if a sample JSON for this object is as below:
{
"Name" : "Comp1",
"Users" : [{
"UserName" : "User1",
"Roles" : [{
"RoleName" : "Guest"
},
{
"RoleName" : "OpUser"
}]
},
{
"UserName" : "User2",
"Roles" : [{
"RoleName" : "Manager"
},
{
"RoleName" : "Principal"
}]
}]
}
The expected output is
Guest,OpUser|Manager,Principal
I wrote below LINQ code to do this.
It works but I believe it can be simplified.
Is this correct or can it be simplified more?
var userList = string.Join("|", company.Users.
SelectMany(c => c.Roles.Select(d => new { user = c.UserName, role = d.RoleName }))
.GroupBy(g => g.user, (key, g) => new { UserName = key, Roles = string.Join(",", g.Select(r=>r.role))})
.Select(i=>i.Roles).ToList());
Why not simply
string.Join("|",
company.Users.Select(u => string.Join(",",
u.Roles.Select(r => r.RoleName)))
)
Related
Environment : -angular for the web app -c# for my api -sql server for the data base
I have this informations from my data base :
public class Traductions
{
public int Id { get; set; }
public int Lot { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public string IdLangage { get; set; }
public string LibelleLangage { get; set; }
public string Traduction { get; set; }
}
If i make a get with the api that return me that format Json informations :
[
{
"Id": 1,
"Lot" : 3,
"Code" : "ABANDONDUTRAITEMENT",
"Description" : "",
"IdLangage": "FR",
"LibelleLangage": "Francais",
"Traduction": "Abandon du traitement"
},
{
"Id": 2,
"Lot" : 3,
"Code" : "ABANDONDUTRAITEMENT",
"Description" : "",
"IdLangage": "EN",
"LibelleLangage": "English",
"Traduction": "Abandonment of processing"
}
]
But i want this type of Json format :
[
{
"Code": "ABANDONDUTRAITEMENT",
"FR": "Abandon du traitement",
"EN": "Abandonment of processing"
},
]
I want to group the informations by Code to return all the Translations (traduction) by Code.
I think i have to do it in my api and not in my angular application
How can i do it ? With linq group by?
somthing like this?
traductions.GroupBy(p => p.Code,
(k, c) => new
{
Code = k,
Data = c
}
).ToList();
https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.groupby?view=net-6.0
you can change the select to be how you want to represent the data in your angular application.
I need to retrieve the following JSON from my CosmosDb, but I think the C# code (which works for a simple JSON structure), needs help.
The response just shows
{ RolePermission[0] }
var response = this.client.CreateDocumentQuery<RolePermission>(
UriFactory.CreateDocumentCollectionUri("demo", "RoleMenus"), queryOptions)
.Where(f => f.RoleName == roleName).AsEnumerable().ToArray();
and the JSON is:
{
"id": "1",
"RoleName": "Admin",
"Menus": [
{
"Item": "Admin",
"Display": "Admin",
"Granted": true
},
{
"Item": "Users",
"Display": "Users",
"Granted": true
}
],
}
The Class defn, I want to get it into is:
public class RolePermission
{
[DisplayName("Role Name")]
public string RoleName { get; set; }
public List<Menus> Menus { get; set; }
}
public class Menus
{
public string Item { get; set; }
public string Display { get; set; }
public bool Granted { get; set; }
}
I just need the menus part of the JSON
Thanks
According to the data that you provided and the code , it should return the list you need "Menus"
with the below query
var response = this.client.CreateDocumentQuery<RolePermission>(UriFactory.CreateDocumentCollectionUri("demo", "RoleMenus"), queryOptions).Where(f => f.RoleName == roleName).ToList();
Make sure you have the correct data inserted with the field RoleName in the container.
I have a json like this:
[
{ "Province1" : [
{ "name" : "city-1" },
{ "name" : "city-2" }
]
},
{ "Province2" : [
{ "name" : "city-1" },
{ "name" : "city-2" }
]
}
]
I want to deserialize it using NewtonsoftJson. I have tried this but the result is null:
public class City {
public string Name { get; set; }
}
var cities = JsonConvert.DeserializeObject<IEnumerable<KeyValuePair<string, List<City>>>(File.ReadAllText(#"jsonPath"));
How should I dersialize it to a class?
After fiddling around with it a bit, I've come up with this structure to deserialize it
class MyDeserializer
{
public static void Deserialize()
{
var json = "[{\"Province1\" : [{\"name\" : \"city-1\" }, {\"name\" : \"city-2\" }] }, {\"Province2\" : [{ \"name\" : \"city-1\" }, { \"name\" : \"city-2\" }] } ]";
var cities = JsonConvert.DeserializeObject<List<Dictionary<string, List<City>>>>(json);
Console.WriteLine(cities[0]["Province1"][0].Name);
}
}
class City
{
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
}
That gives you a dictionary for each province which seems a little unintuitive. But that's how your JSON is structured. If you want to combine all the dictionaries into one, you can do it like this
var cities = JsonConvert.DeserializeObject<List<Dictionary<string, List<City>>>>(json).SelectMany(dict => dict).ToDictionary(pair => pair.Key, pair => pair.Value);
Console.WriteLine(cities["Province1"][0].Name);
There is probably a more elegant solution to this, however this will give you a dictionary of province name with an array of city name Dictionary<string,string[]>
var dict = JArray
.Parse(input)
.Cast<JObject>()
.Select(x => x.Properties().First())
.ToDictionary(
x => x.Name,
x => x.Values().Values().Select(x => x.First.ToString()).ToArray());
I think your structure should be like this :
[
{ "Name": "Province1",
"Cities": [
{ "name": "city-1" },
{ "name": "city-2" }
]
},
{ "Name": "Province2",
"Cities": [
{ "name": "city-1" },
{ "name": "city-2" }
]
}
]
And to deserilize it :
namespace ConsoleApp2 {
public class Province {
public string Name { get; set; }
public List<City> Cities { get; set; }
}
public class City {
public string Name { get; set; }
}
public class ConsoleApp2 {
public static void Main(string[] args) {
List<Province> provinces = JsonConvert.DeserializeObject<List<Province>>(File.ReadAllText("province.json"));
}
}
}
I have a json result return from mongodb each element has array onside it
I would like to query the array element to find a specific node ,
without using the id or email as filter only the token number as a filter (its a unique number)
this is how one of the items json looks like
{
"_id" : ObjectId("5cf67ad97739bfe8525e5353"),
"Email" : "eyal#gmail.com",
"Username" : "eyal",
"Password" : "1234",
"Tokens" : [
{
"Tokennumber" : "123",
"Valid" : "true",
"LoginDate" : ISODate("2019-06-04T00:00:00.000Z")
},
{
"Tokennumber" : "124",
"Valid" : "false",
"LoginDate" : ISODate("2019-06-04T00:00:00.000Z")
},
{
"Tokennumber" : "555",
"Valid" : true,
"LoginDate" : ISODate("2019-06-07T08:32:01.854Z")
}
]
}
I would like to query the json using only one parameter Tokennumber=555
the token number is a unique number so i need to fetch the whole node by querying it by his Tokennumber
the expected result would be the node
with this
data
"_id" : ObjectId("5cf67ad97739bfe8525e5353"),
"Email" : "eyal#gmail.com",
"Username" : "eyal",
"Password" : "1234",
the following mongo query get's the job done using $elemMatch
db.User.aggregate({
"$match": {
"Tokens": {
"$elemMatch": {
"TokenNumber": "234"
}
}
}
})
here's the c# code that generated the above aggregation pipeline. it's using MongoDB.Entities which is just a wrapper for the official driver. [disclaimer: i'm the author]
using MongoDB.Entities;
using System.Linq;
namespace StackOverflow
{
public class Program
{
public class User : Entity
{
public string Email { get; set; }
public Token[] Tokens { get; set; }
}
public class Token
{
public string TokenNumber { get; set; }
public bool Valid { get; set; }
}
static void Main(string[] args)
{
new DB("test");
(new User
{
Email = "email#domain.com",
Tokens = new[] {
new Token{ TokenNumber="123",Valid = false },
new Token{ TokenNumber="234",Valid = true },
new Token{ TokenNumber="456",Valid = false },
}
}).Save();
var user = DB.Queryable<User>()
.Where(u => u.Tokens.Any(t => t.TokenNumber == "234"))
.Single();
}
}
}
EDIT:
since you mentioned you are unable to use the library, the following would be how to do it with the official driver:
var filter = Builders<User>.Filter
.ElemMatch(u => u.Tokens,
t => t.TokenNumber == "234");
var user = collection.Find(filter)
.Single();
var user = collection.Aggregate()
.Match(u => u.Tokens.Any(t => t.TokenNumber == "234"))
.ToList()
.Single();
var user = collection.AsQueryable()
.Where(u => u.Tokens.Any(t => t.TokenNumber == "234"))
.Single();
You can access nodes types using filter.
e.g:
var filter = Builders<YourObject>.Filter.Eq(x => x.Tokens.Any(t => t.Tokennumber == tokerNume), true);
var result = MongoContext.MongoDatabase.GetCollection<YourObject>("YourDocument").Find(filter).FirstOrDefault();
I've registered a class to pull addresses out of the a restaurants collection:
BsonClassMap.RegisterClassMap<RestaurantAddress>(map =>
{
map.MapMember(c => c.Id).SetElementName(("_id"));
map.MapMember(c => c.Building).SetElementName("address.building");
map.MapMember(c => c.Street).SetElementName("address.street");
map.MapMember(c => c.ZipCode).SetElementName("address.zipcode");
});
The Mongo document looks like:
{
"_id" : ObjectId("56bb82621ff72e0d9ba267cb"),
"address" : {
"building" : "6409",
"coord" : [
-74.005289,
40.628886
],
"street" : "11 Avenue",
"zipcode" : "11219"
},
"borough" : "Brooklyn",
"cuisine" : "American ",
"grades" : [
{
"date" : ISODate("2014-07-18T00:00:00.000Z"),
"grade" : "A",
"score" : 12
},
{
"date" : ISODate("2013-07-30T00:00:00.000Z"),
"grade" : "A",
"score" : 12
}
],
"name" : "Regina Caterers",
"restaurant_id" : "40356649"
}
When I get the document, the nested elements are all null though:
[Test]
public void DeserializeToAddress()
{
var collection = _database.GetCollection<RestaurantAddress>("grades");
var address = collection.Find(a => a.Id == new ObjectId("56bb82621ff72e0d9ba267cb")).Limit(1).Single();
Assert.That(address.Id, Is.Not.Null);
Assert.That(address.Building, Is.Not.Null);
Assert.That(address.Street, Is.Not.Null);
}
How should I be referencing nested elements?
The class to serialize into is:
internal class RestaurantAddress
{
public ObjectId Id { get; set; }
public string Building { get; set; }
public string Street { get; set; }
public string ZipCode { get; set; }
public Point CoordsPoint { get; set; }
}
Currenlty, I don't have anything for hyrating the CoordsPoint object. That's for a later excercise.
We currently don't support pulling nested elements out into a parent document. This would be a feature request. You can file that at jira.mongodb.org under the CSHARP project. Alternatively, you can write a custom serializer to handle this particular scenario if you'd like.
Craig