How to filter data and show it in master details view - sapui5

My Data
link https://api.myjson.com/bins/rwqy
Model
var oModel = new sap.ui.model.json.JSONModel("https://api.myjson.com/bins/rwqy");
sap.ui.getCore().setModel(oModel,'data');
I want to create a SplitApp(Master-Details page). I have created the Master page as a List of User Name from the User dataset. The list should contain the firstname.
var oList = new sap.m.List({
id:"listId",
mode: sap.m.ListMode.SingleSelect,
select: function(){
oController.itemSelected();
}
});
var oItemTemplate = new sap.m.StandardListItem({
id: "sList",title:"{data>firstname}"});
oList.bindAggregation("items","data>/user",oItemTemplate );
return new sap.m.Page({
id:"master",
title: "Claims",
content: [oList]
});
Now in details page I want to show the expenses made by that user(when i select a specific user from master view) in a table.
Now my question is how to filter data and use it for the Details view. Example:
If I select User "X" from Master view list, I should get id 1 from the "user" and Expenseno 1,4 and 7 (as they are associated with uid 1) from "expense", finally i will show the expenses of uid 1 in the details view.
Code I am trying
itemSelected: function(){
var app = sap.ui.getCore().byId("appid");//when a item will b selected first we will get instance of our app
var list = sap.ui.getCore().byId("listId");//then will get instance of the list
var sitem = list.getSelectedItem();
var spath = sitem.oBindingContexts.data.sPath;
var oitem = sap.ui.getCore().getModel('data').getProperty(spath);
console.log(oitem); //oitem has Object { id="", firstname="", lastname=""} values of the selected user.
//***how to get only the id from "oitem" and filter with expense table***//
//var Model = new sap.ui.model.json.JSONModel(oitem); // will use it for details
//sap.ui.getCore().setModel(Model,'item');// view(oitem should contain the filtered data)
app.toDetail("detailsid","show");
},
Please Help, Thank you.

I would suppose you reorganize your data source to something like.
[
{
"id": "1",
"firstname": "x",
"lastname": "k",
"expense": [
{
"expenseno": "1",
"uid": "1",
"item": "c",
"amount": "1500"
},
{
"expenseno": "4",
"uid": "1",
"item": "y",
"amount": "1000"
},
{
"expenseno": "7",
"uid": "1",
"item": "q",
"amount": "900"
}
]
},
{
"id": "2",
"firstname": "y",
"lastname": "kalita",
"expense": [
{
"expenseno": "2",
"uid": "2",
"item": "t",
"amount": "1150"
},
{
"expenseno": "5",
"uid": "2",
"item": "t",
"amount": "3500"
}
]
},
{
"id": "3",
"firstname": "z",
"lastname": "kalita",
"expense": [
{
"expenseno": "6",
"uid": "3",
"item": "s",
"amount": "3500"
},
{
"expenseno": "3",
"uid": "3",
"item": "p",
"amount": "500"
}
]
}
]
You can do this from your initial Data set by something like this
myData.user.forEach(function(d,i){
var exp = myData.expense.filter(function(d1){
if(d1.uid === d.id)return true;
});
console.log(exp);
});
After this it is just relative binding from parent. /Expense will give all the expenses of parent.
Hope this helps.

Related

How to query objects from a set of key IDs in Firebase?

Consider the following data structure:
{
"company": {
"idCompany1": {
"data": {
"address": "",
"companyName": "Company 1",
"logo": "assets/Logo1.png",
"nit": "",
"phone": ""
}
},
"idCompany2": {
"data": {
"address": "",
"companyName": "Company 2",
"logo": "assets/Logo2.png",
"nit": "",
"phone": ""
}
},
"idCompany3": {
"data": {
"address": "",
"companyName": "Company 3",
"logo": "assets/Logo3.png",
"nit": "",
"phone": ""
}
}
},
"users": {
"idUser1": {
"data": "user1#test.com",
"companies": {
"idCompany1": true,
"idCompany3": true
}
},
"idUser2": {
"data": "user2#test.com",
"companies": {
"idCompany2": true
}
}
}
}
Basically what I need to do in the case of user1 is to read the data of the companies to which it belongs, this is Company 1 and Company 3. How can I do that?
The way I found, is by obtaining a list of IDs of those companies, which I have in listaIdEmpresas and then consulting each one through a forEach loop in the following way:
Future<List<EmpresaDatosModel>> cargarEmpresaDatosListado(List<String> listaIdEmpresas) async {
final List<EmpresaDatosModel> listaEmpresas = new List();
listaIdEmpresas.forEach((id) async {
Query resp = db.child('company/$id/data');
final snapshot = await resp.once();
final temp = EmpresaDatosModel.fromJson(Map<String,dynamic>.from(snapshot.value));
temp.idEmpresa = id;
listaEmpresas.add(temp);
print('${temp.companyName} up');
await resp.once().then((snapshot) {});
});
listaEmpresas.forEach((element) {print('Emp ${element.companyName}');});
return listaEmpresas;
}
However, this process is not efficient and I need to manage a delay for waiting the loop.
What would be the right way to do query data from a list of Ids directly?

Updating Mongo DB collection field from object to array of objects

I had to change one of the fields of my collection in mongoDB from an object to array of objects containing a lot of data. New documents get inserted without any problem, but when attempted to get old data, it never maps to the original DTO correctly and runs into errors.
subject is the field that was changed in Students collection.
I was wondering is there any way to update all the records so they all have the same data type, without losing any data.
The old version of Student:
{
"_id": "5fb2ae251373a76ae58945df",
"isActive": true,
"details": {
"picture": "http://placehold.it/32x32",
"age": 17,
"eyeColor": "green",
"name": "Vasquez Sparks",
"gender": "male",
"email": "vasquezsparks#orbalix.com",
"phone": "+1 (962) 512-3196",
"address": "619 Emerald Street, Nutrioso, Georgia, 6576"
},
"subject":
{
"id": 0,
"name": "math",
"module": {
"name": "Advanced",
"semester": "second"
}
}
}
This needs to be updated to the new version like this:
{
"_id": "5fb2ae251373a76ae58945df",
"isActive": true,
"details": {
"picture": "http://placehold.it/32x32",
"age": 17,
"eyeColor": "green",
"name": "Vasquez Sparks",
"gender": "male",
"email": "vasquezsparks#orbalix.com",
"phone": "+1 (962) 512-3196",
"address": "619 Emerald Street, Nutrioso, Georgia, 6576"
},
"subject": [
{
"id": 0,
"name": "math",
"module": {
"name": "Advanced",
"semester": "second"
}
},
{
"id": 1,
"name": "history",
"module": {
"name": "Basic",
"semester": "first"
}
},
{
"id": 2,
"name": "English",
"module": {
"name": "Basic",
"semester": "second"
}
}
]
}
I understand there might be a way to rename old collection, create new and insert data based on old one in to new one. I was wondering for some direct way.
The goal is to turn subject into an array of 1 if it is not already an array, otherwise leave it alone. This will do the trick:
update args are (predicate, actions, options).
db.foo.update(
// Match only those docs where subject is an object (i.e. not turned into array):
{$expr: {$eq:[{$type:"$subject"},"object"]}},
// Actions: set subject to be an array containing $subject. You MUST use the pipeline version
// of the update actions to correctly substitute $subject in the expression!
[ {$set: {subject: ["$subject"] }} ],
// Do this for ALL matches, not just first:
{multi:true});
You can run this converter over and over because it will ignore converted docs.
If the goal is to convert and add some new subjects, preserving the first one, then we can set up the additional subjects and concatenate them into one array as follows:
var mmm = [ {id:8, name:"CORN"}, {id:9, name:"DOG"} ];
rc = db.foo.update({$expr: {$eq:[{$type:"$subject"},"object"]}},
[ {$set: {subject: {$concatArrays: [["$subject"], mmm]} }} ],
{multi:true});

Can't get Service Alerts Protobuff to include header_text or description_text using Python gtfs_realtime_pb2 module

We are having difficulty adding header_text and description_text to a Service Alerts protobuff file. We are attempting to match the example shown on this page here.
https://developers.google.com/transit/gtfs-realtime/examples/alerts
Our data starts in the following dictionary:
alerts_dict = {
"header": {
"gtfs_realtime_version": "1",
"timestamp": "1543318671",
"incrementality": "FULL_DATASET"
},
"entity": [{
"497": {
"active_period": [{
"start": 1525320000,
"end": 1546315200
}],
"url": "http://www.capmetro.org/planner",
"effect": 4,
"header_text": "South 183: Airport",
"informed_entity": [{
"route_type": "3",
"route_id": "17",
"trip": "",
"stop_id": "3304"
}, {
"route_type": "3",
"route_id": "350",
"trip": "",
"stop_id": "3304"
}],
"description_text": "Stop closed temporarily",
"cause": 2
},
"460": {
"active_period": [{
"start": 1519876800,
"end": 1546315200
}],
"url": "http://www.capmetro.org/planner",
"effect": 4,
"header_text": "Ave F / Duval Detour",
"informed_entity": [{
"route_type": "3",
"route_id": "7",
"trip": "",
"stop_id": "1167"
}, {
"route_type": "3",
"route_id": "7",
"trip": "",
"stop_id": "1268"
}],
"description_text": "Stop closed temporarily",
"cause": 2
}
}]
}
Our Python code is as follows:
newfeed = gtfs_realtime_pb2.FeedMessage()
newfeedheader = newfeed.header
newfeedheader.gtfs_realtime_version = '2.0'
for alert_id, alert_dict in alerts_dict["entity"][0].iteritems():
print(alert_id)
print(alert_dict)
newentity = newfeed.entity.add()
newalert = newentity.alert
newentity.id = str(alert_id)
newtimerange = newalert.active_period.add()
newtimerange.end = alert_dict['active_period'][0]['end']
newtimerange.start = alert_dict['active_period'][0]['start']
for informed in alert_dict['informed_entity']:
newentityselector = newalert.informed_entity.add()
newentityselector.route_id = informed['route_id']
newentityselector.route_type = int(informed['route_type'])
newentityselector.stop_id = informed['stop_id']
print(alert_dict['description_text'])
newdescription = newalert.header_text
newdescription = alert_dict['description_text']
newalert.cause = alert_dict['cause']
newalert.effect = alert_dict['effect']
pb_feed = newfeed.SerializeToString()
with open("servicealerts.pb", 'wb') as fout:
fout.write(pb_feed)
The frustrating part is that we don't receive any sort of error message. Everything appears to run properly but the resulting pb file doesn't contain the new header_text or description_text items.
We are able to read the pb file using the following code:
feed = gtfs_realtime_pb2.FeedMessage()
response = open("servicealerts.pb")
feed.ParseFromString(response.read())
print(feed)
We truly appreciate any help that anyone can offer in pointing us in the right direction of figuring this out.
I was able to find the answer. This Python Notebook showed that by properly formatting the dictionary the PB could be generated with a few of lines of code.
from google.transit import gtfs_realtime_pb2
from google.protobuf.json_format import MessageToDict
newfeed = gtfs_realtime_pb2.FeedMessage()
ParseDict(alerts_dict, newfeed)
pb_feed = newfeed.SerializeToString()
with open("servicealerts.pb", 'wb') as fout:
fout.write(pb_feed)
All I had to do was format by dictionary properly.
if ALERT_GROUP_ID not in entity_dict.keys():
entity_dict[ALERT_GROUP_ID] = {"id": ALERT_GROUP_ID,
"alert":{
"active_period": [{
"start": int(START_TIME),
"end": int(END_TIME)
}],
"cause": cause_dict.get(CAUSE, ""),
"effect": effect_dict.get(EFFECT),
"url": {
"translation": [{
"text": URL,
"language": "en"
}]
},
"header_text": {
"translation": [{
"text": HEADER_TEXT,
"language": "en"
}]
},
"informed_entity": [{
'route_id': ROUTE_ID,
'route_type': ROUTE_TYPE,
'trip': TRIP,
'stop_id': STOP_ID
}],
"description_text": {
"translation": [{
"text": "Stop closed temporarily",
"language": "en"
}]
},
},
}
# print(entity_dict[ALERT_GROUP_ID]["alert"]['informed_entity'])
else:
entity_dict[ALERT_GROUP_ID]["alert"]['informed_entity'].append({
'route_id': ROUTE_ID,
'route_type': ROUTE_TYPE,
'trip': TRIP,
'stop_id': STOP_ID
})

Adding sections, separated by region_name, to UITableView in Swift

I have some JSON data that I am getting from my database. I can pull it fine and load it into my table view. my issue is separating my JSON data so I can section the tableview. I have JSON array like this
"data": [
{
"ID": 1,
"wilayah_id": 1,
"name": "Jembatan Lima",
"region_name": "region1"
},
{
"ID": 2,
"wilayah_id": 1,
"name": "Kebon Jeruk",
"region_name": "region1"
},
{
"ID": 18,
"wilayah_id": 3,
"name": "Waylunik",
"region_name": "region2"
},
{
"ID": 19,
"wilayah_id": 3,
"name": "Tenggiri",
"region_name": "region2"
},
{
"ID": 25,
"wilayah_id": 3,
"name": "Mesuji",
"region_name": "region3"
},
{
"ID": 26,
"wilayah_id": 4,
"name": "KM 6",
"region_name": "region3"
}
]
What I'm trying to do is separate this data into three parts sort by "region_name" in my table view.
//region model
struct RegionList {
var ID:String
var wilayah_id:String
var name:String
var region_name:String
static var dataSource:[RegionList] {
return [
RegionList.init(ID: "1", wilayah_id: "1", name: "3", region_name: "R1"),
RegionList.init(ID: "1", wilayah_id: "1", name: "3", region_name: "R2"),
RegionList.init(ID: "1", wilayah_id: "1", name: "3", region_name: "R1"),
RegionList.init(ID: "1", wilayah_id: "1", name: "3", region_name: "R2"),
RegionList.init(ID: "1", wilayah_id: "1", name: "3", region_name: "R3")
]
}
}
//Coming Json Array
var arrRegion:[RegionList] = []
//MAKe Section Array by Using Model Class
var regionInSectionArray:[[RegionList]] = []
//Using Dic key in String and value is Model
var usingDicKeySectionArray:[String:[RegionList]] = [:]
// Dummy Data
arrRegion = RegionList.dataSource
//Using Default Dictionary Method to make a group
usingDicKeySectionArray = Dictionary.init(grouping: arrRegion, by: { (region) -> String in
/// Here we are making group dictionary by using region name, you can set by own requirment
//Specify by Region
return region.region_name
})
// You can use it in number of section usingDicKeySectionArray.count
//And number of rowInSection usingDicKeySectionArray[section].count
print(usingDicKeySectionArray.map{$0.key})
//end
///Sorting Keys
//Second option
let sortedKeys = usingDicKeySectionArray.keys.sorted()
sortedKeys.forEach { (key) in
//
let region = usingDicKeySectionArray[key]
regionInSectionArray.append(region ?? [])
}
//USe
//regionInSectionArray.count // in numberOfSection
//regionInSectionArray[section].count // in numberOfRowInSection
//result = ["R1", "R2", "R3"]

MongoDB Database Structure and Best Practices Help

I'm in the process of developing Route Tracking/Optimization software for my refuse collection company and would like some feedback on my current data structure/situation.
Here is a simplified version of my MongoDB structure:
Database: data
Collections:
“customers” - data collection containing all customer data.
[
{
"cust_id": "1001",
"name": "Customer 1",
"address": "123 Fake St",
"city": "Boston"
},
{
"cust_id": "1002",
"name": "Customer 2",
"address": "123 Real St",
"city": "Boston"
},
{
"cust_id": "1003",
"name": "Customer 3",
"address": "12 Elm St",
"city": "Boston"
},
{
"cust_id": "1004",
"name": "Customer 4",
"address": "16 Union St",
"city": "Boston"
},
{
"cust_id": "1005",
"name": "Customer 5",
"address": "13 Massachusetts Ave",
"city": "Boston"
}, { ... }, { ... }, ...
]
“trucks” - data collection containing all truck data.
[
{
"truckid": "21",
"type": "Refuse",
"year": "2011",
"make": "Mack",
"model": "TerraPro Cabover",
"body": "Mcneilus Rear Loader XC",
"capacity": "25 cubic yards"
},
{
"truckid": "22",
"type": "Refuse",
"year": "2009",
"make": "Mack",
"model": "TerraPro Cabover",
"body": "Mcneilus Rear Loader XC",
"capacity": "25 cubic yards"
},
{
"truckid": "12",
"type": "Dump",
"year": "2006",
"make": "Chevrolet",
"model": "C3500 HD",
"body": "Rugby Hydraulic Dump",
"capacity": "15 cubic yards"
}
]
“drivers” - data collection containing all driver data.
[
{
"driverid": "1234",
"name": "John Doe"
},
{
"driverid": "4321",
"name": "Jack Smith"
},
{
"driverid": "3421",
"name": "Don Johnson"
}
]
“route-lists” - data collection containing all predetermined route lists.
[
{
"route_name": "monday_1",
"day": "monday",
"truck": "21",
"stops": [
{
"cust_id": "1001"
},
{
"cust_id": "1010"
},
{
"cust_id": "1002"
}
]
},
{
"route_name": "friday_1",
"day": "friday",
"truck": "12",
"stops": [
{
"cust_id": "1003"
},
{
"cust_id": "1004"
},
{
"cust_id": "1012"
}
]
}
]
"routes" - data collections containing data for all active and completed routes.
[
{
"routeid": "1",
"route_name": "monday1",
"start_time": "04:31 AM",
"status": "active",
"stops": [
{
"customerid": "1001",
"status": "complete",
"start_time": "04:45 AM",
"finish_time": "04:48 AM",
"elapsed_time": "3"
},
{
"customerid": "1010",
"status": "complete",
"start_time": "04:50 AM",
"finish_time": "04:52 AM",
"elapsed_time": "2"
},
{
"customerid": "1002",
"status": "incomplete",
"start_time": "",
"finish_time": "",
"elapsed_time": ""
},
{
"customerid": "1005",
"status": "incomplete",
"start_time": "",
"finish_time": "",
"elapsed_time": ""
}
]
}
]
Here is the process thus far:
Each day drivers begin by Starting a New Route. Before starting a new route drivers must first input data:
driverid
date
truck
Once all data is entered correctly the Start a New Route will begin:
Create new object in collection “routes”
Query collection “route-lists” for “day” + “truck” match and return "stops"
Insert “route-lists” data into “routes” collection
As driver proceeds with his daily stops/tasks the “routes” collection will update accordingly.
On completion of all tasks the driver will then have the ability to Complete the Route Process by simply changing “status” field to “active” from “complete” in the "routes" collection.
That about sums it up. Any feedback, opinions, comments, links, optimization tactics are greatly appreciated.
Thanks in advance for your time.
You database schema looks like for me as 'classic' relational database schema. Mongodb good fit for data denormaliztion. I guess when you display routes you loading all related customers, driver, truck.
If you want make your system really fast you may embedd everything in route collection.
So i suggest following modifications of your schema:
customers - as-is
trucks - as-is
drivers - as-is
route-list:
Embedd data about customers inside stops instead of reference. Also embedd truck. In this case schema will be:
{
"route_name": "monday_1",
"day": "monday",
"truck": {
_id = 1,
// here will be all truck data
},
"stops": [{
"customer": {
_id = 1,
//here will be all customer data
}
}, {
"customer": {
_id = 2,
//here will be all customer data
}
}]
}
routes:
When driver starting new route copy route from route-list and in addition embedd driver information:
{
//copy all route-list data (just make new id for the current route and leave reference to routes-list. In this case you will able to sync route with route-list.)
"_id": "1",
route_list_id: 1,
"start_time": "04:31 AM",
"status": "active",
driver: {
//embedd all driver data here
},
"stops": [{
"customer": {
//all customer data
},
"status": "complete",
"start_time": "04:45 AM",
"finish_time": "04:48 AM",
"elapsed_time": "3"
}]
}
I guess you asking yourself what do if driver, customer or other denormalized data changed in main collection. Yeah, you need update all denormalized data within other collections. You will probably need update billions of documents (depends on your system size) and it's okay. You can do it async if it will take much time.
What benfits in above data structure?
Each document contains all data that you may need to display in your application. So, for instance, you no need load related customers, driver, truck when you need display routes.
You can make any difficult queries to your database. For example in your schema you can build query that will return all routes thats contains stops in stop of customer with name = "Bill" (you need load customer by name first, get id, and look by customer id in your current schema).
Probably you asking yourself that your data can be unsynchronized in some cases, but to solve this you just need build a few unit test to ensure that you update your denormolized data correctly.
Hope above will help you to see the world from not relational side, from document database point of view.