I am using MVC4 and C#.
I have a KendoUI Treeview and I'd like to populate it with data from RavenDB.
In the demo they use this:
public JsonResult Employees(int? id)
{
var dataContext = new NorthwindDataContext();
var employees = from e in dataContext.Employees
where (id.HasValue ? e.ReportsTo == id : e.ReportsTo == null)
select new {
id = e.EmployeeID,
Name = e.FirstName + " " + e.LastName,
hasChildren = e.Employees.Any()
};
return Json(employees, JsonRequestBehavior.AllowGet);
}
Notice the argument "id" - it's an int. In RavenDb document ID's are strings eg. myDco/231...
Imagine this is a standard document:
{
"CreationDate": "12/12/2012 8:07:59 PM",
"Name": "jkljklk",
"Type": "kljkljkljkljkl",
"Description": "ljkljklj",
"CreatedByUser": "ljklklkljklj",
"Deleted": false,
"Status": "NEW",
"Parent": "product/546"
}
How would I populate the treeview?
There should not be any problem to use string instead of that int. You just need to fetch the needed records depending on that string parameter passed to the Action method.
I figured this out.
I changed my RavenDB Document to include a list of all its children:
{
"CreationDate": "12/12/2012 9:33:34 PM",
"Name": "hohoho",
"Type": "hohohoh",
"Description": "hohohoh",
"CreatedByUser": "hohohoh",
"Deleted": false,
"Status": "NEW",
"Parent": "ohohohoh",
"Children": [
"item/1",
"item/2",
"item/3"
]
}
I then returned a list of my items to the View via the controller and then iterated through them, appending all the children to their correct parent nodes:
#(Html.Kendo().TreeView().Name("TreeView").DragAndDrop(true)
.Items(treeview =>
{
foreach (var myItem in Model)
{
var myItemName = myItem.Name;
var children = myItem.Children;
treeview.Add().Text(myItemName ).Expanded(false).Items(branch =>
{
if (children != null)
{
foreach (var child in children)
{
branch.Add().Text(child);
}
}
});
}
}
))
Anyway, thanks for the responses :)
Hope this helps someone else one day.
Related
I have a document like:
{
"Id":"1",
"Name":"product1",
"Categories":["Cat1",
"Cat2",
"Cat3"]
},
{
"Id":"2",
"Name":"product2",
"Categories":["Cat3",
"Cat2",
"Cat6"]
}
Now I want return a distinct List of all categories.
I tried CollapseParameter, but it doesn't work.
var foo = _solr.Query(new SolrQuery("*"), new QueryOptions
{
Collapse = new CollapseParameters("Categories")
});
var bar= results.CollapseExpand; //NULL
How can I get a list of all categories without iterating through all the documents? Do I have to create new Documents for the categories? Or should I work with Faceting?
It looks like the JSON is not valid. So I created a solution changing the Json:
{
"items": [{
"Id": "1",
"Name": "product1",
"Categories": ["Cat1", "Cat2", "Cat3"]
}, {
"Id": "2",
"Name": "product2",
"Categories": ["Cat3", "Cat2", "Cat6"]
}]
}
And then, I used foreach and LINQ structure:
var x = categories.SelectMany(item => item.Categories).Distinct();
If you are using solr and you want all distinct value for specific field then must start reading solr faceting doc, its amazing.
Only add below query in your query and you we get full list of all distinct categories.
&facet=true&facet.field=Categories
That's it, It will gives result set as you expected.
QueryOptions options = new QueryOptions
{
StartOrCursor = new StartOrCursor.Start(0),
Rows = 1,
Facet = new FacetParameters { Queries = new[] { new SolrFacetFieldQuery("Categories") } }
};
var result = _solrConnection.Query(new SolrQuery("*"), options);
if (result.FacetFields.ContainsKey("Categories"))
{
return result.FacetFields["Categories"]
.Where(li => li.Value > 0)
.Select(y=> y.Key)
.ToList();
}
That's my current solution. It works, but I hoped there would be a better way. I'm searching for a result just to get all the categories.
My root data has several sub collections, and I need to do a where clause on 2 of them, sample:
{
"id": "000092224369_0030",
....
"orderData": {
...
"request_secondary": {
"_type": "request_secondary",
"secondary_requests": [{
"secondary_description":"do something" }]
},
"partnership": {
"contacts": [
{
"role": "AG",
"first_name": "LIEBENS Eric",
"last_name": null,
"_type": "contact",
"email": "eric.liebens#gmail.com",
"tel1": "0495-543905",
"tel2": null,
"vat": null
},
{
"role": "ZO",
"first_name": "Coralie",
"last_name": "Demeyere",
"_type": "contact",
"email": "coralie.demeyere#ores.net",
"tel1": "069/256533",
"tel2": null,
"vat": null
},
{
"role": "ZR",
"first_name": "GASBARRO Gianni",
"last_name": null,
"_type": "contact",
"email": null,
"tel1": "0495-385479-0",
"tel2": null,
"vat": "BE0474281005"
}
],
...
Here I need to do a query that bring back the record where any secondary_description equals a text, or a contact with a name with that text.
It should translate to sql for in something this:
SELECT c.id from c
join x in c.orderData.request_secondary
join y in c.orderData.partnership.contacts
where x.secondary_description ='sometin' or y.first_name= 'sometin'
I have tried this solution:
How to query sub document (list type) in Cosmos Db
It works great with one sub collection, but I have no idea how i could get this to work with several selectmany...
Is there any way I can do this in linq?
Thanks!
Based on your description, i think your SQL needs to be tweaked a little bit.
SELECT c.id from c
join x in c.orderData.request_secondary.secondary_requests
join y in c.orderData.partnership.contacts
where x.secondary_description ='something' or y.first_name= 'something'
However, there's going to be duplicate data in the results.So , I also suggestion you adopt the stored procedure which I answered in the thread:How to query sub document (list type) in Cosmos Db.
function sample() {
var collection = getContext().getCollection();
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT * FROM root r',
function (err, feed, options) {
if (err) throw err;
if (!feed || !feed.length) getContext().getResponse().setBody('no docs found');
else {
var returnResult = [];
for(var i = 0;i<feed.length;i++){
var isContinue = true;
var array1 = feed[i].orderData.request_secondary.secondary_requests;
var array2 = feed[i].orderData.partnership.contacts;
for(var j = 0;i<array1.length;j++){
if(array1[j].secondary_description == 'something'){
returnResult.push(feed[i]);
isContinue=false;
break;
}
}
if(isContinue){
for(var k = 0;i<array2.length;k++){
if(array2[j].first_name == 'something'){
returnResult.push(feed[i]);
break;
}
}
}
}
getContext().getResponse().setBody(returnResult);
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
Update Answer:
You could build LINQ from SQL follow the doc.
client.CreateDocumentQuery().SelectMany((x) =>
x.orderData.requestSecondary.secondaryRequests.Where(
s=>s.secondaryDescription == "something"
) ||
x.orderData.partnership.contacts.Where(
c=>c.firstName == "something"
)
However , i think you still need to resolve the duplicate data of the result set on your client.
Hope it helps you.
I have a document in MongoDB that looks like that:
{
"Id":"123",
"Product": "test",
"Tags":[
{
"Name": "name",
"Categories": [
{
//item
},
{
//item
}
]
},
{
"Name": "name",
"Categories": [
{
//item
},
{
//item
}
]
}
]
}
Now, I need to add a new Item and it needs to be added to all of the categories of the Tags element of that Product by its Id.
For example, when I'll insert Item 3 the document should look like this:
{
"Id":"123",
"Product": "test",
"Tags":[
{
"Name": "name",
"Categories": [
{
//item 1
},
{
//item 2
},
{
//item 3
}
]
},
{
"Name": "name",
"Categories": [
{
//item 1
},
{
//item 2
},
{
//item 3
}
]
}
]
}
and same goes for removing an item, it needs to be removed from all of the categories as well.
Is there a way to do that with the C# MongoDB Driver without pulling the object and "manually" updating them?
You can try something like below in 2.5 driver with 3.6 version.
Finds the document with filter criteria and update which includes new positional identifier to update multiple elements in array inside UpdateOne method.
$[] updates all the Tags arrays to include new item in all Categories array. It acts as a placeholder for updating all elements in array.
Push
var filter = Builders<Product>.Filter.Eq("Id", "123");
var update = Builders<Product>.Update.Push("Tags.$[].Categories", "Item 3");
var result = collection.UpdateOne(filter, update);
Pull
var filter = Builders<Product>.Filter.Eq("Id", "123");
var update = Builders<Product>.Update.Pull("Tags.$[].Categories", "Item 3");
var result = collection.UpdateOne(filter, update);
Additional Information:
You can set the ArrayFilters options in UpdateOptions for applying query criteria on nested array to control what elements to update.
For example to update all the Categories in Tags array where each tag has Name name.
var filter = Builders<Product>.Filter.Eq("Id", "123");
var update = Builders<Product>.Update.Push("Tags.$[t].Categories", "Item 3");
var arrayFilters = new List<ArrayFilterDefinition>{ new ArrayFilterDefinition(new BsonDocument("t.Name", "name")) };
var updateOptions = new UpdateOptions({ArrayFilters = arrayFilters});
var result = collection.UpdateOne(filter, update, updateOptions);
I have a web application in which I'm retrieving some data into bootstrap table, what i want to do now is to use jQuery DataTable instead of the current as it has too much useful features.
Currently I'm retrieving the data from the server side using OOP approach, where a class object represents a data row in a particular table, and this object includes a dictionary which stores column names and values.
What I'm doing now is that I'm retrieving these class objects and append each dictionary of each object in a List<Item> and then serialize this list using JavaScriptSerializer object, and this object returns the following JSON format:
[
{
"slno":"2",
"status_message":"Lights still flashing",
"crm_services_id":"1", "subject_id":"Lights are flashing",
"severity_id":"5",
"user_id":"husain.alhamali",
"status_id":"1"
},
{
"slno":"3",
"status_message":"lights working fine",
"crm_services_id":"2",
"subject_id":"Lights are flashing",
"severity_id":"3",
"user_id":"husain.alhamali",
"status_id":"2"
}
]
When i tried to use this object to fill my DataTable AJAX I've got an error says:
Invalid JSON response
I saw some examples of a valid JSON response that is acceptable to a DataTable which is as follow:
{
"data": [
[
"Tiger Nixon",
"System Architect",
"Edinburgh",
"5421",
"2011/04/25",
"$320,800"
],
[
"Garrett Winters",
"Accountant",
"Tokyo",
"8422",
"2011/07/25",
"$170,750"
]
}
Now my question is is there any tool or plugin that could re-format my JSON string into an acceptable format like the one above?
With this HTML:
<table id="example"></table>
This JS will create a table:
var data = [{
"slno": "2",
"status_message": "Lights still flashing",
"crm_services_id": "1",
"subject_id": "Lights are flashing",
"severity_id": "5",
"user_id": "husain.alhamali",
"status_id": "1"
}, {
"slno": "3",
"status_message": "lights working fine",
"crm_services_id": "2",
"subject_id": "Lights are flashing",
"severity_id": "3",
"user_id": "husain.alhamali",
"status_id": "2"
}];
function getColumns(){
for(var i = 0; i < data.length; i++){
let columnsArray = [];
var keys = Object.keys(data[i]);
for(k in Object.keys(data[i])){
if(data[i].hasOwnProperty(keys[k])){
columnsArray.push({
"data":keys[k]
});
}
}
return columnsArray;
}
}
$(document).ready(function() {
var table = $('#example').DataTable({
"columns": getColumns(),
"data": data
});
});
Working example. Hope that helps.
dataTable require json data in return from ajax response having following keys
1. data
2. draw
3. recordsTotal
4. recordsFiltered
Use this:
var data = list.Select(u => u.GetType()
.GetProperties()
.Select(p => p.GetValue(u, null)));
example
public class User
{
public int userId { get; set; }
public string name { get; set; }
}
public class Programm
{
static void Main()
{
var list = new List<User>();
list.Add(new User
{
userId = 1,
name = "name 1",
});
list.Add(new User
{
userId = 2,
name = "name 2",
});
var data = list.Select(u => u.GetType()
.GetProperties()
.Select(p => p.GetValue(u, null)));
Console.WriteLine(new JavaScriptSerializer().Serialize(new
{
data = data
}));
}
}
result
{
"data" : [
["1", "name 1"],
["2", "name 2"]
]
}
I'm trying to extract a list of dates for a property of all children nodes on a JToken but cannot get the syntax correct.
I want to get a list of dates in property "timeStamp": "2013-09-11T00:30:00Z" so I can determine the min/max dates for all child nodes.
I've tried the following which returns an anonymous type and makes it difficult to use the returned object.
var timeStamps = Jarr.Select(x => new
{
timeStamp = (DateTime)x.SelectToken("timeStamp")
});
How can I get say a List<string> or List<DateTime> only of all child timestamps?
Is it possible to get a Dictionary<string, DateTime> of id, timestamp?
The Json looks like this, so essentially from LEVEL1 I want to check all children, children of children for the same property.
{
"children": [
{
"type": "LEVEL2",
"name": "Item1",
"id": "1.7193",
"timeStamp": "2013-09-11T00:30:00Z",
},
{
"type": "LEVEL2",
"name": "Item2",
"id": "1.7194",
"timeStamp": "2013-09-11T00:30:00Z",
},
{
"type": "LEVEL2",
"name": "Item3",
"id": "1.7191",
"timeStamp": "2013-09-11T00:30:00Z",
}
],
"type": "LEVEL1",
"name": "Stock-FRT54443",
"id": "1000145",
"countryCode": "en"
}
and method
void AddNodes(TreeView treeView, JObject jObj, TreeNodeCollection parent)
{
JToken Jarr = null;
Dictionary<string, string> marketProperties = new Dictionary<string, string>();
foreach (var property in jObj.Properties())
{
if (property.Name == "children")
{
Jarr = property.Value;
}
else
{
string key = property.Name;
string prop = property.Value.ToString();
marketProperties.Add(key, prop);
}
}
if (marketProperties["type"] == "LEVEL1")
{
//Not working!
var timeStamps = Jarr["timeStamp"].Values<string>();
}
}
When you use the 'new' keyword it's going to create an anonymous type. You're creating a list of objects with a timestamp property rather than a list of DateTimes. All you need to do to get your date list is to change it to:
DateTime timeStamps = Jarr.Select(x => (DateTime)x.SelectToken("timeStamp")).ToList();
It's also possible to get a dictionary:
Dict<string,DateTime> dictionary = Jarr["children"].ToDictionary(x=>x["Id"].ToString(),x=>(DateTime)(x["timeStamp"]));
The second is untested but should give you the general idea.