I am trying to replicate what would be a left join in MySql in Mongo. I have a collection named Clients and another collection name Orders.
In the clients collection is have:
client_PK, FirstName, LastName, Company
In the orders collection I have:
order_PK, client_fk, OrderDate, OrderAmount,
So i know that can use embedded documents but for the sake of this question i am looking to use the reference model.
My question is, using these two collections how would I construct a table or object similar to a left join in mysql? I know this is a document db not a relational db but im using sql language just to give you an idea of what im trying to accomplish. In MySql it would look like this:
SELECT * FROM orders LEFT JOIN clients ON clients.client_PK = orders.client_fk
with this i could now construct a table that looked like:
FirstName | LastName | Company | OrderDate | OrderAmount
then i could repeat the rows using a while loop to display all orders and display the clients name with the order. Again i know mongo isn't a relational db but i am assuming there is a way simulate a table using two collections.
Thank you.
You almost certainly want to be storing these data all in the same MongoCollection (even in just a denormalization collection).
If you absolutely can't do that, though, and if your set is small, you can do something similar to this (since you asked about PHP):
<?php
// gather orders
$orders = iterator_to_array($mongodb->orders->find());
$joinedOrders = array();
// gather clients
foreach ($db->clients->find() as $client) {
// iterate orders (like a left join)
foreach ($orders as $order) {
// make a "joinedOrders" record for each join match
if ($order['client_fk'] == $client['client_PK']) {
$joinedOrders[] = array_merge($order, $client);
}
}
}
// result is now in $joinedOrders
This is, however, almost always a bad idea. (-: You really should be denormalizing your data, or using a relational database to store/query relational data.
i am assuming there is a way simulate a table using two collections
MongoDB does not have any tool for doing this. You are basically going to have "roll your own" joins. At the basic level, this means that you will have to write nested for loops and build a result set in your code.
Doing this type of "extra logic" is pretty common in MongoDB because of the lack of joins. If you're seeing this pattern a lot, you may want to consider using SQL for part of your data.
Related
I have two queries that I need to run to obtain, a list of contracts and a list of sales, due to the fact that there is a duplicate contract for each customer I have written a query that will return customer_id and the date of their final contract while joining on our products table to filter for certain products. another query returns a list of sales for a given area by connecting to a couple of tables as well is their anyway after calling these queries I could join them using php .
$contracts = DB::table('contracts as c').....
$leads= DB::table('contracts as l')..
so after creating these two collections that both have the column customer_id, i want to join them using PHP if these where both tables in my database this would be a simple left_join, however, I can't figure out a way to do it with the output of the quarry .... thanks in advance for all the help. I have been doing some research and think i need to map somehow
$leads = $leads->map(function ($item, $key) {
$single_lead = $contract->where('l.customer_id',$item->spp.customer_id);
return collect($item)->merge($single_lead);
something like this but this is not working and I'm stuck so I should be going through each item in leads and then merge it with the contract information that has the same customer_id
Your question wasn't very clear but giving you a hint to do left join,
You can do it as:
$query = DB::table('contracts')->leftJoin('customer','customer.id','=','contracts.customer_id')->get()
You can see it in the Laravel Docs
I'm working on an existing application that uses some JOIN statements to create "immutable" objects (i.e. the results are always JOINed to create a processable object - results from only one table will be meaningless).
For example:
SELECT r.*,u.user_username,u.user_pic FROM articles r INNER JOIN users u ON u.user_id=r.article_author WHERE ...
will yield a result of type, let's say, ArticleWithUser that is necessary to display an article with the author details (like a blog post).
Now, I need to make a table featured_items which contains the columnsitem_type (article, file, comment, etc.) and item_id (the article's, file's or comment's id), and query it to get a list of the featured items of some type.
Assuming tables other than articles contain whole objects that do not need JOINing with other tables, I can simply pull them with a dynamicially generated query like
SELECT some_table.* FROM featured_items RIGHT JOIN some_table ON some_table.id = featured_items.item_id WHERE featured_items.type = X
But what if I need to get a featured item from the aforementioned type ArticleWithUser? I cannot use the dynamically generated query because the syntax will not suit two JOINs.
So, my question is: is there a better practice to retrieve results that are always combined together? Maybe do the second JOIN on the application end?
Or do I have to write special code for each of those combined results types?
Thank you!
a view can be thot of as like a table for the faint of heart.
https://dev.mysql.com/doc/refman/5.0/en/create-view.html
views can incorporate joins. and other views. keep in mind that upon creation, they take a snapshot of the columns in existence at that time on underlying tables, so Alter Table stmts adding columns to those tables are not picked up in select *.
An old article which I consider required reading on the subject of MySQL Views:
By Peter Zaitsev
To answer your question as to whether they are widely used, they are a major part of the database developer's toolkit, and in some situations offer significant benefits, which have more to do with indexing than with the nature of views, per se.
I need to JOIN 2 tables (lets say User & Order table) for reporting module in my web app.
The problems are:
The User table is located on the different server & different
DBMS from the Order table. Technically it is a different system, so the User table is located on SQL Server DB, meanwhile the Order table is located on MySQL DB.
I couldn't use SQL Server's Linked Server because my company policy doesn't allow it. So, I coudn't JOIN them directly with SQL code. They want me to use Web Service instead of linked server.
The result of JOIN operation from those tables has a large number of rows (maybe more than 10,000 rows because the data aimed for reporting). So, I think it was a horrible thing to mapping them using Web Service.
So I came up with this:
I collected 2 query result from different models and join them with my app code (I'm using PHP with CodeIgniter) :
// First result
$userData = $this->userModel->getAllUser();
// Second result
$orderData = $this->orderModel->getAllOrder();
The $userData contains all user entities with the following columns:
[UserId, Username, Address, PhoneNumber, etc..]
And the $orderData contains all order entities with the following columns:
[OrderId, UserId, Date, etc..]
But is it possible to join those two query results in PHP / CodeIgniter?
How about the performance regarding the large amount of data?
Should I just use Web Service as suggested or there's another solution to accomplish this?
Thanks in advance :)
A few things to think about:
Do you actually need to return all user and order records in one single go
Do you actually want to return all rows for these two types of record
Would you be better off with a Report module for these report queries?
Would plain SQL syntax be a smarter move than trying to shim this into existence with the CodeIgniter "Active Record" (renamed Query Builder in 3.0)
Is JOIN really so bad? It is not a UNION, you want the data to be related.
I would recommend you limit your data returns, SELECT only the fields you actually require, make a new Report model to avoid trying to mess up your generic models and do this with raw SQL.
Complicated things get all the more complicated when you try too hard to stick to rules like "1 table = 1 model" and "User::getAllFoos + controller processing > Report::getMonthlyOrderStats()".
specs: PHP 5 with mySQL built on top of Codeigniter Framework.
I have a database table called game and then sport specific tables like soccerGame and footballGame. these sport specific tables have a gameId field linking back to the game table. I have corresponding classes game and soccerGame/footballGame, which both extend game.
When I look up game information to display to the user, I'm having trouble figuring out how to dynamically link the two tables. i'm curious if it's possible to get all the information with with one query. The problem is, I need to query the game table first to figure out the sport name.
if that's not possible, my next thought is to do it with two queries. have my game_model query the game table, then based off the sport name, call the appropriate sport specific model (i.e. soccer_game_model) and get the sport specific info.
I would also pass the game object into the soccer_model, and the soccer_model would use that object to build me a soccerGame object. this seems a little silly to me because i'm building the parent object and then giving it to the extending class to make a whole new object?
thoughts?
thanks for the help.
EDIT:
game table
gameId
sport (soccer, basketball, football, etc)
date
other data
soccerGame table
soccerGameId
gameId
soccer specific information
footballGame table
footballGameId
gameId
football specific information
and so on for other sports
So I need to know what the sport is before I can decide which sport specific table I need to pull info from.
UPDATE:
Thanks all for the input. It seems like dynamic SQL is only possible through stored procedures, something I'm not well versed on right now. And even with them it's still a little messy. Right now I will go the two query route, one to get the sport name, and then a switch to get the right model.
From the PHP side of things now, it seems a little silly to get a game object, pass it to, say, my soccer_game_model, and then have that return me a soccer_game object, which is a child of the original game. Is that how it has to be done? or am I missing something from an OO perspective here?
To extend on Devin Young's answer, you would achieve this using Codeigniter's active record class like so:
public function get_game_by_id($game_id, $table)
{
return $this->db->join('game', 'game.id = ' . $table . '.gameId', 'left')
->where($table . '.gameId', $game_id)
->get('game')
->result();
}
So you're joining the table by the gameId which is shared, then using a where clause to find the correct one. Finally you use result() to return an array of objects.
EDIT: I've added a second table paramater to allow you to pass in the name of the table you can join either soccerGame, footballGame table etc.
If you don't know which sport to choose at this point in the program then you may want to take a step back and look at how you can add that so you do know. I would be reluctant to add multiple joins to all sport tables as you''ll run into issues down the line.
UPDATE
Consider passing the "sport" parameter when you look up game data. As a hidden field, most likely. You can then use a switch statement in your model:
switch($gameValue) {
case 'football': $gameTable = "footballGame"; break;
case 'soccer': $gameTable = "soccerGame"; break;
}
Then base your query off this:
"SELECT *
FROM ". $gameTable . "
...etc
You can combine the tables with joins. http://www.w3schools.com/sql/sql_join.asp
For example, if you need to get all the data from game and footballGame based on a footballGameId of 15:
SELECT *
FROM footballGame a
LEFT OUTER JOIN game b ON a.id = b.gameId
WHERE footballGameId = 15
Check this Stack Overflow answer for options on how to do it via a standard query. Then you can turn it into active record if you want (though that may be complicated and not worth your time if you don't need DB-agnostic calls in your app).
Fow what it's worth, there's nothing wrong with doing multiple queries, it just might be slower than an alternative. Try a few options, see what works best for you and your app.
I have a question related to a web app that I developed in PHP, MYSQL.
basically part 1 is :
I display results in the form of table say for software testing.
ID Prod_Name Set Date Result Platform
1 Alpha1 Pro1 01.01.01 PASS 2.3.1.2_OS
Now, I have divided the tables accordingly
Table Name: Results
ID, Name, Date, Result
Table Name : Set
ID, Set_Name, Prod_name
Table Name : Platform
ID, Platform_Name, Set_Name
Now, ID in each table is an incremented value and does not relate to anything else.
My php app, starts with fetching the results from 'Results' table. Since I want SET to be displayed for every row, I am making an another connection to the database and using the query
select Set_name
from Set
where Prod_name = row['Name'] // row['Name'] is fetched from the results table.
now I also want to display platform which I am extracting it from Platform table using the above method i.e making another connection and passing Set_Name = row['Set_Name'] from the Set table.
Now for my application is there any other way to achieve the same result ?
Typically, for large web based applications, if data is coming from a database server is making multiple connection to a DB server a feasible option?
Please do not consider the fact that with MySQL declaring a connection statement once will do the needful but what about MSSQL server? Do we need to write a long sql statement with several joins/selfjoins/unions and use those variables all over the application?
How is the application design for this case will be?
Can anyonce give me some ideas please?
Thanks.
For pretty much any flavour of database, a single SELECT statement which joins three tables will perform better than three separate statements querying a table apiece. Joining is what relational databases do.
I may not have understood everything, but here is something similar. First, let's make an ER model.
Now, because you don't seem to like joins, create a view in the database.
CREATE VIEW v_test AS
SELECT TestID, ProductName, TestName, Date, Result, PlatformName
FROM Product AS p
JOIN Test AS t ON t.ProductID = p.ProductID
JOIN Platform AS f ON f.PlatformID = t.PlatformID;
With this in place, you can simply use:
SELECT * FROM v_test WHERE ProductName = 'Alpha1'
You may also take a look at this question/answer with a similar scenario.