Trying to use $lookup to retrieve data from two collections of same database - mongodb-query

I am trying to retrieve data from two collections posts and users with userId and ObjectId(_id) respectively as joining condition using $lookup. But it just returns me data from collection posts along with an empty array. Here is my query.
db.posts.aggregate([{
$lookup: {
from: 'users',
localField: 'userId',
foreignField: '_id',
as: 'user_data'
}
}]).pretty();

Related

Whats the best method of making arrays of joined tables in Big Query?

I'm trying to do some data transformation inside of Big Query, with SQL.
Let's say I have three tables:
Customer - data about the customer, like age, etc
Subscriptions - data about what subscriptions the user have
Engagements - data about how the customers have interacted with digital products.
I'd like to collect this inside of one table, using nested fields.
I can join all these tables, but I'd like to aggregate them to arrays.
So, instead of three tables I get this:
id:123,
name:David,
age:30,
subscritions: [{
name:sub1
price:10
},
{
name:sub2
price:20
}],
engagment: [{
event:visited_product_x
time:2020-06-10
},
{
event:visited_product_y
time:2020-06-10
}]
Of course I've used array_agg in SELECT. And that works great, when adding only one table. However, when adding another one, I get duplicate rows, which I don't want. So, I guess I shouldn't use array_agg in SELECT, but rather somewhere else.
But whats the best way of solving this?
You can use subqueries to construct the fields. Something like this:
select c.*,
(select array_agg(s)
from substriptions s
where s.user_id = c.user_id
) as subscriptions,
(select array_agg(e)
from engagements e
where e.user_id = c.user_id
) as engagements
from customers c

Sequelize select with aggregate includes bad attributes => error

The models are Person and Team with a M:1 relationship.
The query that fails:
db.Person.findAll({
attributes: [ [sequelize.fn('COUNT', sequelize.col('*')), 'count']],
include: [{model: db.Team, required: true}], // to force inner join
group: ['team.team_id']
}).complete(function(err, data) {
...
});
The generated SQL is:
SELECT "person"."person_id",
COUNT(*) AS "count",
"team"."team_id" AS "team.team_id",
"team"."team_name" AS "team.team_name",
"team"."team_email" AS "team.team_email",
"team"."team_lead" AS "team.team_lead"
FROM "person" AS "person" INNER JOIN "team" AS "team"
ON "person"."team_id" = "team"."team_id"
GROUP BY "team"."team_id";
Obviously, the person.person_id included in the SELECT clause, screws it up, with Postgres complaining correctly that:
ERROR: column "person.person_id" must appear in the `GROUP BY` clause or be used in an aggregate function
It seems that the attributes option is taken into account since the COUNT appears correctly, but all the rest of the columns in the SELECT clause are added by default.
Is there another way (besides attributes) to explicitly define which columns appear in the SELECT clause or is this a bug?
I'm using Sequelize v2.0.3.
Sequelize will always add the primary key to the selected fields. Currently there is no way to disable that.
Perhaps adding DISTINCT ON as suggested here https://stackoverflow.com/a/19723716/800016 to person_id could fix the issue?
Otherwise, feel free to open an issue on the sequelize bug tracker

Ruby on Rails: Select from database where column equals a value from array

If I have an array of IDs from a table (table1) in my database. Is there a way of querying another table (table2) to select all the records where a column equals a value equal to one of the IDs from table1.
My code so far is:
LabQuestion.where("product_id=#{Product.where(:brand_id => brand_id).pluck(:id)}")
In this code, I am trying to retrieve all the Lab Questions which are linked to all the products from a brand. This code does not work, but I've tried to demonstrate my needs.
Assuming you have setup your relations properly, you can use joins to join the two tables and query them like this:
LabQuestion.joins(:product).where(:products => { :brand_id => brand_id })
You can use includes instead of joins as below
LabQuestion.includes(:product).where(:products => { :brand_id => brand_id })

Selecting from multiple tables with Yii's CActiveDataProvider

I have 3 tables: Topics, Users and Details (those are some of the tables of a custom forum)
Topics contains (among other usual fields) the id (FK) of the user that created the topic.
Users contains nick/pass and id (PK)
Details contains (among other usual fields) the id (FK) of the user.
Relations:
One user can have one 1 detail.
One user can have multiple topics, but a topic can be created only by one user.
Topic relations:
return array(
'user' => array(self::BELONGS_TO, 'User', 'User_iduser'),
);
User relations:
return array(
'details' => array(self::HAS_ONE, 'Details', 'User_iduser'),
);
I'm trying to get a list with Topics and User details (let's say for example the topic name and the user's name).
Currently I have this:
$dataProvider=new CActiveDataProvider('Topic', array(
'criteria'=>array(
'with'=>array('user.details')
)
));
But as you can imagine, it's not working (read as in it's not selecting anything from the tbles Users or Details).
What's wrong with my code?
+++++++++++++++
This code selects fields from the table user (and the topic table):
Topic::model()->with('user')->findAll();
But this one won't select from details, users and topic:
Topic::model()->with('user.details')->findAll();
Also, I need a CActiveDataProvider solution as I need it for zii widgets (means, even if some kind of modification on the Topic::model()->with().... code get's to select from the 3 tables it won't be really helpful)
EDIT: (SQL log from Yii)
Querying SQL: SELECT COUNT(DISTINCT `t`.`idtema`) FROM `tema` `t` LEFT
OUTER JOIN `usuario` `usuarioIdusuario` ON
(`t`.`Usuario_idusuario`=`usuarioIdusuario`.`idusuario`) LEFT OUTER JOIN
`detallesusuario` `detallesusuario` ON
(`detallesusuario`.`Usuario_idusuario`=`usuarioIdusuario`.`idusuario`)
Querying SQL: SELECT `t`.`idtema` AS `t0_c0`, `t`.`Usuario_idusuario` AS
`t0_c1`, `t`.`Categoria_idcategoria` AS `t0_c2`, `t`.`tema` AS `t0_c3`,
`t`.`fecha_hora` AS `t0_c4`, `usuarioIdusuario`.`idusuario` AS `t1_c0`,
`usuarioIdusuario`.`nick` AS `t1_c1`, `usuarioIdusuario`.`contrasena` AS
`t1_c2`, `usuarioIdusuario`.`email` AS `t1_c3`,
`detallesusuario`.`Usuario_idusuario` AS `t2_c0`,
`detallesusuario`.`nombre` AS `t2_c1`, `detallesusuario`.`apellidos` AS
`t2_c2`, `detallesusuario`.`cumpleanos` AS `t2_c3`,
`detallesusuario`.`telefono1` AS `t2_c4`, `detallesusuario`.`telefono2` AS
`t2_c5` FROM `tema` `t` LEFT OUTER JOIN `usuario` `usuarioIdusuario` ON
(`t`.`Usuario_idusuario`=`usuarioIdusuario`.`idusuario`) LEFT OUTER JOIN
`detallesusuario` `detallesusuario` ON
(`detallesusuario`.`Usuario_idusuario`=`usuarioIdusuario`.`idusuario`)
LIMIT 10
Try this
$dataProvider=new CActiveDataProvider('Topic', array(
'criteria'=>array(
'with'=>array('user'=>array('alias'=>'user','with'=>array('details'=>array('alias'=>'details'))))
)
));
And
Topic::model()->with(array('user'=>array('alias'=>'user','with'=>array('details'=>array('alias'=>'details')))))->findAll();
instead of the line
'with'=>array('user.details')
use
'with'=>array('user')
then add
$criteria->compare( 'user.details', $query, true );
$criteria->together = true;
}
*Where $query is a variable that will be searched in column details

Lithium with left join

I'm new with Lithium.I need to do a left join.This is the query I need.
SELECT `title`,`body`,`user_id`,`users`.`username`,`users`.`id`
FROM `posts` LEFT JOIN `users`
ON `user_id` = `users`.`id`
I try to do something like this.
$conditions['user_id'] = $this->data['user_id'];
$posts = Post::all(array(
'conditions' => $conditions,
'fields' => array('title','body','username'),
'join' => array('source' => 'posts',
'type' => 'LEFT',
'constraint' => array('post.user_id' => 'Users.id')),
))->data();
There is a great tutorial (using a blog as an example) here which explains using Relationships in Lithium, Relationships make using relational data and JOINS simpler.
You can also check out the official docs as well as this answer: How do I perform joins with lithium models?
Once you have your Relationships set on your Models you can do your JOINS as simply as:
$posts = Posts::find('all', array(
'with' => 'Users'
));
There are a couple differant types of Relationships in Lithium, which roughly corrspond to differant types of JOINS ...
hasOne: the current object is linked to a single object of another type
hasMany: the current object is linked to many objects of another type
belongsTo: the current object is owned and marked as related to
another object