Laravel 4 rest api non-implicit action routing and left join - rest

I am pretty new to Laravel but I certainly like Laravel 4. I am stuck at two points -
The first is that - I have a non crud action method in a controller that has to do a left join with two tables and return the result. There are two tables, Employees and Departments. I am trying to get all assigned and non-assigned employees for creating an association between them. This action method is inside "EmployeeController". It is named as "allAssignedEmployees". I tried the following routing but seems it doesn't work :
Route::resource('employees/assignedEmployees/{deptId}', 'EmployeesController#assignedEmployees');
Secondly, I am not kind of too sure about my left join. The following is what I made out of googling
$unassignedEmployees = DB::table('employee')
->join('department', function($join)
{
$join->on('department.employee_id', '=', 'employee.id');
})
->where('department.id', '=', $deptId)
->get();
Apparently what I wanted in SQL is - select * from employee emp left join department dept on dept.employee_id = employee.id and employee.dept_id = 2
The other related questions unanswered I had in mind are - how to log in Laravel 4? Especially SQL queries or general log statements. Is there an inbuilt logging support.
I know its a lot of questions, but I am sure the answers will help my learning process hence thanks for your time.

First I'm not being rude but you should have studied Documentation First at least.
Now coming to your questions:
About Resource Controller:
Route::resource('employees', 'EmployeesController');
This single route declaration creates multiple routes to handle a variety of RESTful actions on the employees resource. Likewise, the generated controller will already have stubbed methods for each of these actions with notes informing you which URIs and verbs they handle.
Actions Handled By Resource Controller
Verb Path Action Route Name
GET /employees index employees.index
GET /employees/create create employees.create
POST /employees store employees.store
GET /employees/{id} show employees.show
GET /employees/{id}/edit edit employees.edit
PUT/PATCH /employees/{id} update employees.update
DELETE /employees/{id} destroy employees.destroy
So if you have created resource controller then get routes like employees/{id} will be handled by controllers show method.
But if you want specific method to handle then you have to route it like this
Route::get('employees/assignedEmployees/{deptId}',''EmployeesController#assignedEmployees'');
And regarding logging read here

Related

How to improve performance on nested graphql connections when using pagination

I'm trying to implement some kind of a basic social network project. It has Posts, Comments and Likes like any other.
A post can have many comments
A post can have many likes
A post can have one author
I have a /posts route on the client application. It lists the Posts by paginating and shows their title, image, authorName, commentCount and likesCount.
The graphql query is like this;
query {
posts(first: 10, after: "123456") {
totalCount
edges {
node {
id
title
imageUrl
author {
id
username
}
comments {
totalCount
}
likes {
totalCount
}
}
}
}
}
I'm using apollo-server, TypeORM, PostgreSQL and dataloader. I use dataloader to get author of each post. I simply batch the requested authorIds with dataloader, get authors from PostgreSQL with a where user.id in authorIds query, map the query result to the each authorId. You know, the most basic type of usage of dataloader.
But when I try to query the comments or likes connection under each post, I got stuck. I could use the same technique and use postId for them if there was no pagination. But now I have to include filter parameters for the pagination. And there maybe other filter parameters for some where condition as well.
I've found the cacheKeyFn option of dataloader. I simply create a string key for the passed filter object to the dataloader, and it doesn't duplicate them. It just passes the unique ones to the batchFn. But I can't create a sql query with TypeORM to get the results for each first, after, orderBy arguments separately and map the results back to the function which called the dataloader.
I've searched the spectrum.chat source code and I think they don't allow users to query nested connections. Also tried Github GraphQL Explorer and it lets you query nested connections.
Is there any recommended way to achieve this? I understood how to pass an object to dataloader and batch them using cacheKeyFn, but I can't figure out how to get the results from PostgreSQL in one query and map the results to return from the loader.
Thanks!
So, if you restrict things a bit, this is doable. The restriction is to only allowed batched connections on the first page of results, e.g. so all the connections you're fetching in parallel are being done with the parameters. This is a reasonable constraint because it lets you do things like get the first 10 feed items and the first 3 comments for each of them, which represents a fairly typical use case. Trying to support independent pagination within a single query is unlikely to fulfil any real world use cases for a UI, so it's likely an over-optimisation. With this in mind, you can support the "for each parent get the first N children" use case with PostgreSQL using window.
It's a bit fiddly, but there are answers floating around which will get you in the right direction: Grouped LIMIT in PostgreSQL: show the first N rows for each group?
So use dateloader how you are with cacheKeyFn, and let your loader function recognise whether you can perform the optimisation (e.g. after is null and all other arguments are the same). If you can optimise, use a windowing query, otherwise do unoptimised queries in parallel as you would normally.

TSQL list of business rules in MDS

I need help with querying my business rules in SQL!
I have created couple of business rules in MDS web service to validate my master data and found out that 2 % of my data is not complying with the rules. Now I have created a SQL subscription view to report on the invalid data in PowerBI. In my PowerBI report I need to tell the business user why the data is invalid but I cannot since the subscription view only tells where the data is invalid but not why the data is invalid. So I need to know how I might query my business rules from MDS database in SQL and map it with my PowerBI data model. Is there a way to query the list of business rules from MDS database?
OK, so there are multiple ways to go about this. Here are some solutions, pls choose one that suits your scenario.
1. SQL - List of all Business Rules
The following query will retrieve the list of all Active Business Rules created in MDS.
SELECT *
FROM [MDM].[mdm].[viw_SYSTEM_SCHEMA_BUSINESSRULES]
WHERE Model_Name = 'YourModelName'
AND BusinessRule_StatusName = 'Active'
You can, of course, further filter by Entity_Name, etc.
The important columns in your case are going to be:
[BusinessRule_Name]
[BusinessRule_Description]
[BusinessRule_RuleConditionText]
[BusinessRule_RuleActionText]
Note: The challenge in your scenario, I think, is going to be that the Subscription View of the entity does not have IDs of the exact Business Rules that failed. So I'm not sure how you'll tie these 2 together (failing Rows -> List of Business Rules). Also remember that each row may have more than 1 business rule that failed.
2. using View viw_SYSTEM_USER_VALIDATION
This is a view that has a historical list of all business rules (+row info) that failed. You may use the view in this way:
SELECT
DISTINCT ValidationIssue_ID, Version_ID, VersionName, Model_ID, ModelName, Entity_ID, EntityName, Hierarchy_ID, HierarchyName, Member_ID, MemberCode, MemberType_ID, MemberType, ConditionText, ActionText, BusinessRuleID, BusinessRuleName, PriorityRank, DateCreated, NotificationStatus_ID, NotificationStatus
FROM [MDM].[mdm].[viw_SYSTEM_USER_VALIDATION]
WHERE --CAST(DateCreated as DATE) = CAST(GETDATE() as DATE) AND
ModelName = 'YourModelName'
--AND EntityName IN ('Entity_1','Entity_2') -- Use this to Filter on specific Entities
Here, use the columns Model_ID, Entity_ID and Member_ID/MemberCode to identify the specific model, entity & row that failed.
Columns BusinessRuleName, ConditionText & ActionText will give your users additional info on the Business Rule that failed.
Note:
One issue with using this view is that even though, let's say, your failure condition was resolved the next day by the user, the view will still show that on a certain date, a validation had failed. (via column DateCreated).
Also note that the same failed data row will appear multiple times here if multiple Business Rules on the same row failed validation (there will be different BusinessRuleID/Name, etc). Just something to take note of.
Similarly, the same row may appear multiple times if it has failed again & again at different times. To workaround this, and if your final report can do with that, add a WHERE clause on the DateCreated column so that you only get to see any row that Failed today. The commented out line of code <--CAST(DateCreated as DATE) = CAST(GETDATE() as DATE) AND> does the same. If you can't use that, just make sure the data row are distinct. However, if you do this, remember that if something Failed yesterday (and is still in the Failed status), it may not show up.
My suggestion would be to use a slightly modified version of Solution #2:
Get the list of Failed Rows from your Subscription View (the data row's ValidationStatus is actually still 'Failed'), then JOIN with viw_SYSTEM_USER_VALIDATION making sure that you only select the row with MAX(DateCreated) value (of course for the same data row AND Business Rule).
Best of luck and if you find anything else while solving this issue, do share your learning here with all of us.
Lastly, if you found this useful, pls remember to Mark it as the Answer :)

TYPO3 7.6 Backend module to list values from several tables

I have been struggling for some time now and I can't really find anyone having done the same thing before.
I'm creating a backend module in TYPO3 7.6 which belongs to a shop extension.
The shop extension with the backend module was created with the extension builder. The shop has the following three models:
Product (products which can be ordered through the shop)
Productsorder (link to the customer)
ProductsorderPosition (the ordered product, the ordered amount and size and the link to the Productsorder)
The customers are of a model type from a different extension. These customers are linked to fe_users.
Now what I wanna do in my backend module is getting an overview to all these orders listed with the customer, some information about the fe_user and of course the product. I have created a sql-query, which does exactly that:
SELECT p.productname, p.productpriceperpiece,
pop.amount, pop.size,
h.name, h.address, h.zipcode, h.city, h.email, h.phone,
f.first_name, f.last_name, f.email
FROM `tx_gipdshop_domain_model_productorderposition` AS pop
JOIN `tx_gipdshop_domain_model_product` AS p ON pop.products = p.uid
JOIN `tx_gipdshop_domain_model_productsorder` AS po ON pop.productorder = po.uid
JOIN `tx_gipleasedisturbhotels_domain_model_hotel` AS h ON po.hotel = h.uid
JOIN `fe_users` AS f ON h.feuser = f.uid
If I use this query from the product repository it gives back the right amount of data records but they're of type product and the products are all "empty" (uid = 0 etc).
I've added an additional action for this in the product controller (getOrdersAction) and in the repository containing the query I've added a method findAllOrders.
I'm still rather a beginner in TYPO3 but I can somehow understand why it returns data sets of type Product when the query is called from the ProductRepository. But what I do not know is how I can get all the information from the query above and list it in the backend module.
I've already thought about moving the query to the ProductsorderPositionRepository but I would probably be faced with a similar problem, it would only return the information from the ProductsorderPosition and everything else would be left out.
Can someone point me to the right direction?
Would I need to create another model with separate repository and controller? Isn't there an easier way?
If you need more information, just ask! ;)
First of all, you are doing a joined query with subsets of data mixed from multiple tables. There is nothing against this.
Because of this, there is no "model" which has the mixed datasets.
If you are using the default query thing in a repository, the magic behind the repository assumes that the result of the query statement reflects the defined base model for this repository.
Moving the query function to another repository does not solve the problem.
You have not provided the code snippet you are executing the sql statement, so I assume you have used the query thing in the repository to execute the statement. Something like this:
$result = $query->statement('
SELECT p.productname, p.productpriceperpiece,
pop.amount, pop.size,
h.name, h.address, h.zipcode, h.city, h.email, h.phone,
f.first_name, f.last_name, f.email
FROM `tx_gipdshop_domain_model_productorderposition` AS pop
JOIN `tx_gipdshop_domain_model_product` AS p ON pop.products = p.uid
JOIN `tx_gipdshop_domain_model_productsorder` AS po ON pop.productorder = po.uid
JOIN `tx_gipleasedisturbhotels_domain_model_hotel` AS h ON po.hotel = h.uid
JOIN `fe_users` AS f ON h.feuser = f.uid', NULL);
or have used the query building stuff.
First solution
The first and simpliest solution would be to retrieve the result as plain php array. Before TYPO3 7.0 you could have done this by using this:
$query->getQuerySettings()->setReturnRawQueryResult(TRUE);
With TYPO3 7.0 this deprecated method was removed from the core.
The only way is to define the query and call $query->execute(TRUE); for now.
This should return the data in pure array form.
This is the simpliest one, but as we are in the extbase context this should not be suffering enough.
Second Solution - no, just an idea that I would try next
The second solution means that you have some work to do and is for now only a suggestion, because I have not tried this by myself.
Create a model with the properties and getter/setters for the result columns of your query
Create a corresponding repository
Third solution
Not nice, but if nothing else works, fall back to the old TYPO3 v4 query methods:
$GLOBALS['TYPO3_DB']->exec_SELECTgetRows([...]))
and replace this with the QueryBuilder in/for TYPO3 v8.
This is really not nice.
I hope I could direct you to the right way, even if not giving a full solving solution.

Tableau MarkLogic Data Modelling

I am using Tableau with MarkLogic. I have the following XML Structure
<CustomerInformation CustomerId="1">
<CustomerBasicInformation>
<CustomerTitle></CustomerTitle>
<CustomerFirstName></CustomerFirstName>
<CustomerMiddleName></CustomerMiddleName>
<CustomerLastName></CustomerLastName>
</CustomerBasicInformation>
<CustomerEmplyomentDetails>
<CustomerEmployer>
<EmployerName IsCurrentEmployer=""></EmployerName>
<CustomerDesignation></CustomerDesignation>
<EmployerLocation></EmployerLocation>
<CustomerTenure></CustomerTenure>
</CustomerEmployer>
<CustomerEmplyomentDetails>
<PolcyDetails>
<Policy PolicyId="">
<PolicyName></PolicyName>
<PolicyType></PolicyType>
<PolicyCategory></PolicyCategory>
<QuoteNumber></QuoteNumber>
<PolicyClaimDetails>
<PolicyClaim ClaimId="">
<PolicyClaimedOn></PolicyClaimedOn>
<PolicyClaimType></PolicyClaimType>
<PolicyClaimantName></PolicyClaimantName>
</PolicyClaim>
</PolicyClaimDetails>
<PolicyComplaintDetails>
<PolicyComplaint ComplaintId="">
<PolicyComplaintStatus></PolicyComplaintStatus>
<PolicyComplaintOn></PolicyComplaintOn>
</PolicyComplaint>
</PolicyComplaintDetails>
<BillingDetails>
<Billing BillingId="">
<BillingAmount></BillingAmount>
<BillingMode></BillingMode>
</Billing>
</BillingDetails>
</Policy>
<Policy PolicyId="">
<PolicyName></PolicyName>
<PolicyType></PolicyType>
<PolicyCategory></PolicyCategory>
<QuoteNumber></QuoteNumber>
<PolicyClaimDetails>
<PolicyClaim ClaimId="">
<PolicyClaimedOn></PolicyClaimedOn>
<PolicyClaimType></PolicyClaimType>
<PolicyClaimantName></PolicyClaimantName>
</PolicyClaim>
</PolicyClaimDetails>
<PolicyComplaintDetails>
<PolicyComplaint ComplaintId="">
<PolicyComplaintStatus></PolicyComplaintStatus>
<PolicyComplaintOn></PolicyComplaintOn>
</PolicyComplaint>
</PolicyComplaintDetails>
<BillingDetails>
<Billing BillingId="">
<BillingAmount></BillingAmount>
<BillingMode></BillingMode>
</Billing>
</BillingDetails>
</Policy>
</PolcyDetails>
</CustomerInformation>
I have created a view on above structure.
Initially I have created a single view for all elements, but on Tableau I got duplicate values as well as Cartesian join result.
So to tackle this, I used approach of fragment root.
Since there can be multiple PolicyDetails for single customer. I have created fragment root on Policy.
Similarly Claims, Complaints, Billing, Quote can be multiple for single policy, I have created fragment root on each one of them.
Now after doing this it resolves the duplicate issue as well as Cartesian join result set. It gives unique set of record for each entities (CustomerInfo, Policy, Claims, Complaints, Quote, Employer, Billing).
However I am not able to relate this entities with each other (as in foreign-primary key).
I have created the following view with element scope and all. I am pasting only Customer and Policy details, if this resolves other entities can be similarly managed
view:create(
"InsurancePOC",
"CustomerBasicInfo",
view:element-view-scope(xs:QName("CustomerInformation")),
(
view:column("CustomerId", cts:element-attribute-reference(xs:QName("CustomerInformation"), xs:QName("CustomerId"))),
view:column("PolicyId", cts:element-attribute-reference(xs:QName("Policy"), xs:QName("PolicyId"))),
view:column("QuoteNumber", cts:element-attribute-reference(xs:QName("Quote"), xs:QName("QuoteNumber"))),
view:column("ComplaintId", cts:element-attribute-reference(xs:QName("PolicyComplaint"), xs:QName("ComplaintId"))),
view:column("BillingId", cts:element-attribute-reference(xs:QName("Billing"), xs:QName("BillingId"))),:)
view:column("CustomerFirstName", cts:element-reference(xs:QName("CustomerFirstName"))),
view:column("CustomerLastName", cts:element-reference(xs:QName("CustomerLastName")))
),
(),
()
),
view:create(
"InsurancePOC",
"PolcyInfo",
view:element-view-scope(xs:QName("Policy")),
(
view:column("PolicyId", cts:element-attribute-reference(xs:QName("Policy"), xs:QName("PolicyId"))),
view:column("PolicyName", cts:element-reference(xs:QName("PolicyName"))),
view:column("PolicyType", cts:element-reference(xs:QName("PolicyType")))
),
(),
()
)
All pre-requisites like element-range index and all is been done.
I am trying to relate these entities using view:column("PolicyId", cts:element-attribute-reference(xs:QName("Policy"), xs:QName("PolicyId"))) in CustomerBasicInfo view.
If I do so it shows zero results in Tableau or Query console.
If I remove it, gives unique record but without any relationship with each other.
All I want is to achieve relationship between Policy-Customer
Kindly go through the code snippet, if more clarification required please let me know
The getting of cartesian join results is a known issue with the SQL views driven from Range indexes in MarkLogic, particularly with aggregate docs like above.
The simplest way to solve it for SQL views would be to split your docs into separate Policies, with embedded copies of the customer into. That could mean a fair amount of data duplication if customers often have multiple policies.
You could also consider taking these docs apart, and storing policies and customer details separately, with id refs from policy to customer, so that you can join them together afterwards, in Tableau, or SQL.
MarkLogic 9 comes with a new feature though, that would prevent the need for all this. It is called Template Driven Extraction. It also provides SQL views on data, but works in a different way. It is driven with a match pattern (called the context) that controls the rows in the view. You would use Policy as context in this case. From there you would use relative paths to go up the tree to customer details, and down to get policy details.
TDE templates are installed using tde:template-insert. The documentation of that function shows a simple example of such a TDE:
http://docs.marklogic.com/tde:template-insert
You can also play around with tde:node-data-extract first, to get the hang of it.
HTH!

Can web2py serve REST data of many-to-may tables via parse_as_rest?

I need to serve REST data about a many-to-many relationship. I've been playing with web2py's lovely parse_as_rest functionality, but can't quite get the many-to-many thing working.
As an example, let's take standard users and groups.
Tables:
user
id
user_name
group
id
group_name
membership
id
user_id
group_id
What pattern do I need to use to serve a url that will give me all group_name's that a user belongs to?
patterns = [
"/user[user]",
"/user[user]/id/{user.id}",
"/user[user]/id/{user.id}/membership[membership.user_id]",
# This is the line that I can't make yet:
#"/user[user]/id/{user.id}/membership[membership.user_id]/group<WHAT GOES HERE>",
"/group[group]",
"/group[group]/id/{group.id}",
]
parser = db.parse_as_rest(patterns, args, vars)
With the non-commented lines above, I can get to these urls:
.../user
.../user/id/1
.../user/id/1/membership
.../group
.../group/id/3
URL #3 shows me all my memberships, and I can then make several separate calls to URL #5 to get the group_name values, but there's got to be a way to do this with one call.
Help me StackOverflow! You're my only hope.
EDIT: Fixed bad cutting and pasting.
This question is in top of Google search for that topic.
Just start building query from the many-to-many table.
/user[membership]/id/{membership.user_id}/groups[group.id]
You don't really need 'user' table for this request.
Then request to "/user/id/22/groups" will give you all groups not only their IDs.