I have a query where I want only Id and name of the collection back to reduce the network traffic. I am able to get what i want from the database with the following part of the query
ShipToCities = Return.As<IEnumerable<string>>("COLLECT( [shipTo.InternalId, shipTo.Name])")
but the issue is i get back the data like this:
[ [ "IN.KA.MANG", "Mangalore" ], [ "IN.KA.MANG", "Mangalore" ], [ "IN.KA.BANG", "Bangalore" ] ]
but how can I map it to a C# object like
public class CityFound
{
public string CityId { get; set; }
public string CityName { get; set; }
}
is there a way to use some converter to achieve this without me having to use some ugly string manipulation myself?
UPDATE 1:
Actually my query is fairly complex and only way to get the data that I can think of is to handcraft the query like below to reduce the :
//selectedLoadQuery below is a complex query based on user selection...
var query = selectedLoadQuery
.Match("(load)-[:SHIPPED_BY]->(shipper)-[r:HAS_TRANSPORTER]->(transporter)")
.With("load, transporter, shipper, user, count(DISTINCT r) as MyClients")
.Match("p=(shipFrom:City)<-[:SHIP_FROM_CITY]-(load)-[:SHIP_TO_CITY]->(shipTo:City)")
.With("p, load, shipFrom, shipTo, transporter, MyClients")
.Return((load, shipFrom, shipTo) => new
{
TotalShipments = load.CountDistinct(),
FromMyClients = Return.As<long>("MyClients"),
ShipFromCities = Return.As<IEnumerable<string>>("COLLECT( [shipFrom.InternalId, shipFrom.Name])"),
ShipToCities = Return.As<IEnumerable<string>>("COLLECT( [shipTo.InternalId, shipTo.Name])"),
});
Regards
Kiran
You don't need to get so creative. You're only getting into this issue because you're hand crafting such a complex query that flattens out the structure of the data.
Create a class that describes what's in the node:
public class ShippingDestination
{
public long InternalId { get; set; }
public string Name { get; set; }
}
Use this to light up the following syntax in your Return statement:
var cities = graphClient
.Match(...)
.Return(shipTo => new {
Id = shipTo.As<ShippingDestination>().InternalId,
Name = shipTo.As<ShippingDestination>().Name,
})
.Results;
Related
[
{
"articles": [
[
"2016-03-04",
6
],
[
"2016-03-05",
10
],
[
"2016-03-06",
11
]
],
"accession": "00000446-201301000-00018"
},
{
"articles": [
[
"2016-03-04",
1
],
[
"2016-03-08",
17
],
[
"2016-03-09",
10
]
],
"accession": "00000446-201301000-00019"
}]
List is input { "Accession"= "00000446-201301000-00018", "Date"= "635926464000000000","Rank" =2},{ "Accession" = "00000446-201301000-00019", "Date" = "635931648000000000","Rank" = 2}
I want json data exactly like this,data is coming from list and list is dynamically growing.Form list, I want all dates and rank club to gether for the same accession number.
I want to use newtonsoft json custom serlization to convert my list to json.
What you want to do does not need any Custom Formatter, you just have to re-structure your data, Here is an example for restructuring a list based on Entity class to the new required one.
class Entity
{
public string Accession { get; set; }
public string Date { get; set; }
public int Rank { get; set; }
}
Add this line if you need to read the list from Json
var list = JsonConvert.DeserializeObject<List<Entity>>(input);
Here is the code for changing the structure of data to array based articles.
var translatedAsArray = list.GroupBy(e => e.Accession)
.Select(g =>
new {
//change new 'object[]' to 'new' to make the article an object
//you can convert i.Date, i.Rank and g.Key to anything you want here
Articles = g.Select(i => new object[] { i.Date , i.Rank }),
Accessing = g.Key
}
);
var json = JsonConvert.SerializeObject(translatedAsArray, Formatting.Indented);
Model
public class FinalList
{
public string accession {get;set;}
public List<ArticlesDetails> Articles{get;set;}
}
public class ArticlesDetails
{
public DateTime Date{get;set;}
public int number{get;set;}
}
Use ObjectContent instead of StringContent so we let the formatter (i.e. JsonMediaTypeFormatter) to deal with the serialization and deserialization
In config
config.Formatters.Insert(0, new YourCustomFormatter());
config.Formatters.Insert(1, new JsonMediaTypeFormatter());
and disable post in your custom formatter so that JsonMediaTypeFormatter desrializes the complex data
Imagine these classes in C#:
public class User
{
public int Id { get; set; }
public string Username { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Text { get; set; }
public string[] HashTags { get; set; }
}
each user can add a post and the relation between them would be the Author, each post could have an array of hash-tags which each of them is going to be a separate node in graph.
when i am going to save each post, I would find the user in grph, create a post node and relate them with a Author Relationship.
the Question is how can I create and relate each hashTag to the post in the same query. (to be inside a transaction).
How could I dynamically add item to query to create it.
the problem is that it could not create node and the relation in one line of create.
Here is what I have tried so far:
var cypherQuery = Db.Instance.Cypher
.Match("(user:User)")
.Where((User user) => user.Username == "XYZ")
.Create("user-[:Author]->(post:Post {newPost})")
.WithParam("newPost", new Post() {Id = 1, Text = "Here is my post about #someHashTag"});
//How to relate this node to the number of hashTags in Post Object???
cypherQuery.ExecuteWithoutResults();
is it good to be in single query or should i divide it in multiple round trips.
I Have tried something with foeach but it seams that the post does not have any value inside the foreach loop:
I have tried something like this:
var cypherCommand = Db.Instance.Cypher
.Match("(user:User)")
.Where((User user) => user.Username == "farvashani")
.Create("user-[:Author]->(post:Post {newPost})")
.WithParam("newPost", "here is my post about #Tag1 and Tag2")
.ForEach(#"(hashtag in {hashTags}|
MERGE post-[:Mentioned]->(hash:HashTag {Text: hashtag}))")
.WithParam("hashTags", new string[] {"Tag1", "Tag2"});
cypherCommand.ExecuteWithoutResults();
In my opinion, i think you have to pre-process the Text property first.
String text = ""Here is my post about #someHashTag""; // For example
List<String> hashTags = new List<String>();
int cnt = 0;
foreach (Match match in Regex.Matches(text, #"(?<!\w)#\w+"))
{
hashTags.Add(match.Value);
}
Then create new instance of Post:
Post newPost = new Post
{
Id = 1,
Text = "Here is my post about #someHashTag",
hashTags = hashTags
};
So, you can use this Cypher:
var cypherCommand = Db.Instance.Cypher
.Match("(user:User)")
.Where((User user) => user.Username == "farvashani")
.Create("user-[:Author]->(post:Post {newPost})")
.WithParam(new {newPost}).ExecuteWithoutResults();
Hope this help.
P/s: Could I ask you a question? Do you think it is better for you to retrieve the separated graph if you use each hashTag as a label of Post? newPost:someHashTag for example?
I'm running the following AJAX call.
var submission = {};
submission.input = [];
submission.input.push({ Id: "{ab684cb0-a5a4-4158-ac07-adff49c0c30f}" });
submission.input.push({ Id: "{bb684cb0-a5a4-4158-ac07-adff49c0c30f}" });
$.ajax({
url: "http://" + "localhost:49642/Controller/Action",
data: submission
});
It works as supposed to and in my controller I can see two elements. However, the Id fields is all-zeros. I'm certain I failed to match the definition of the object on the server-side but I'm to annoyed and frustrated right now to generate more suggestions how to shove the data to the service.
The data model is like this.
public class Thingy
{
public Guid Id { get; set; }
public IEnumerable<Guid> Blobb { get; set; }
}
I've tried to use different bracket types, apostrophes and such enclosing the guids on client-side. To no avail. What can I have forgotten?!
Edit
I need to clarify the structural definition of my information object. The controller is set up to receive the following.
public ActionResult SelectionStorage(IEnumerable<Stuff> stuff)
{
Session["Stuff"] = stuff;
return null;
}
The definition of the Stuff class is more complex but the following will suffice as a POC.
public class Stuff
{
public Guid Id { get; set; }
public IEnumerable<Guid> Ids { get; set; }
public Dictionary<String, decimal> Amounts { get; set; }
}
So, on the client, I'm performing the following set up of the submitted data object.
var submission = {};
var subIds = [];
subIds.push("{ab684cb0-a5a4-4158-ac07-adff49c0c30f}");
subIds.push("{bb684cb0-a5a4-4158-ac07-adff49c0c30f}");
submission.input = [];
submission.input.push({
Id: "{cb684cb0-a5a4-4158-ac07-adff49c0c30f}",
Ids: subIds,
Amounts: null
});
Note that the Amounts will differ from null but that headache I haven't even got to, yet.
Edit 2
New try - a simpler approach. In JS I send the following.
var stuff = {};
stuff.input = [];
stuff.input.push("{ab684cb0-a5a4-4158-ac07-adff49c0c30f}");
stuff.input.push("{bb684cb0-a5a4-4158-ac07-adff49c0c30f}");
$.ajax({
url: ...,
data: stuff,
type: "POST",
success: ...,
error: ...
});
On recieving end in C# I have this.
public ActionResult MyAction(List<String> input) { ... }
This gives null. I can't see why.
You should be able to simplify the jquery. With what you have here you don't need the submission. If you are sending a complex list back to the controller you need to name your variables but since you are just sending a string back you don't need to do that. Try changing your data to
var input = [];
input.push("{ab684cb0-a5a4-4158-ac07-adff49c0c30f}");
input.push("{bb684cb0-a5a4-4158-ac07-adff49c0c30f}");
then in the ajax call
data: input,
or
data: Json.stringify(input);
then on your controller
public ActionResult Action(List<String> input){...
Edit:
try changing your jquery to this:
var stuff= {};
stuff.Id = "{cb684cb0-a5a4-4158-ac07-adff49c0c30f}";
stuff.Ids= [];
stuff.Ids.push("{ab684cb0-a5a4-4158-ac07-adff49c0c30f}");
stuff.Ids.push("{bb684cb0-a5a4-4158-ac07-adff49c0c30f}");
then in your ajax have data: stuff, or data: Json.stringify(stuff),
To keep things simple, I have this class:
public class Contact
{
public string Name { get; set; }
public string[] Emails { get; set; }
}
I have a collection of contacts = IEnumerable<Contact>
I need to find all contacts in that collection that have, let's say a text "xxx" in their email addresses (they may have multiple emails).
Something like that doesn't work of course:
var found = contacts.Where(c => c.Emails.Where(e => e.Contains("xxx")));
I am wondering how to build such query using lambda expression?
Thanks.
Use Any instead of Where in the inner expression:
var found = contacts.Where(c => c.Emails.Any(e => e.Contains("xxx")));
Try this
var found = contacts.Where(c => c.Emails.Where(e => e.Contains("xxx")).Count() > 0);
This will return all the contacts according to the specified email condition.
Good Luck !!
I am using a charting javascript library that expects its data in a specific JSON format - without property names.
I have an object in my Model that I am using to return the data to the charts. This looks as follows:
public class ChartData
{
public string Key { get; set; }
public int Value { get; set; }
}
An action looks as follows:
public ActionResult AssetsPerFloor(Guid id)
{
var results = from a in surveyRepository.GetAssetsForBuidling(id)
group a by a.Room.Floor into g
select new ChartData{ Key = g.Key.ToString(), Value = g.Count() };
return Json(results);
}
This returns JSON in the format [{"Key":"Main Building","Value":1}]
However, the chart requires no property names, eg: [[5, 2], [6, 3], [8, 2]]
Is there anyway I can return the results in this format. I'm sure there's a simple trick to it, but I cant think of it.
As far as I understand, it needs to return a multi-dimensional array. Try this :
var results =
(from a in surveyRepository.GetAssetsForBuidling(id)
group a by a.Room.Floor into g
select new ChartData{ Key = g.Key.ToString(), Value = g.Count() })
.Select(x => new string[] { x.Key, x.Value.ToString() };
return Json(results);