LINQ to SQL: Selecting a one-to-many relationship - linq

I've got two tables (articles and tags) that have a one-to-many relationship.
I remember seeing somewhere that I can create nested objects/arrays/etc from that relationship. The output of which I would like in a format such as (in JSON format):
{1 : {
id : 1,
title : 'article title',
tags : ({
id : 16,
tagname : 'first tag'
},{
id : 23,
tagname : 'another tag'
})
}
I'm creating an internal knowledge base system with a list view similar to the front page of stack overflow (that's the way I'd like to display the tags).
How would I go about doing this? A subquery? Thanks.

If I understand your question correctly you're looking for the SelectMany function which lets you 'unroll' nested structures like yours. SelectMany is indeed executed in Query syntax by a sub-query:
IEnumerable<Tag> =
from article in Articles
from tag in article.Tags
select tag;
In method form:
IEnumerable<Tag> tags = Articles.SelectMany(a => a.Tags);

Related

Can I directly get a nested list in my Doctrine result?

Sorry if the question is poorly phrased, I couldn't come up with a good way of describing my issue.
So basically, I'm using the Doctrine query builder to try and a list of training sessions from my Session entity. For each session, I need to fetch basic properties such as the name and date, but I also need to fetch the list of participants. There is a one-to-many relation between the entities Session and Participant, as there may be several participants to a given session. I would simply need a list of these participants, nested in each item of the list of sessions. Something like this:
[
{
"session_name": "name1",
"session_date": "date1",
...
"participants": [
{
"participant_name": "john1",
...
},
{
"participant_name": "john2",
...
},
...
],
},
{
"session_name": "name2",
"session_date": "date2",
...
"participants": [
{
"participant_name": "john3",
...
},
{
"participant_name": "john4",
...
},
...
],
},
...
]
This seems to me like it should be quite basic, but for the life of me I cannot get it to work with JOINs, subqueries, etc. The closest I got was this error, which does imply I'm trying to get a nested array (but it won't let me):
SQLSTATE[21000]: Cardinality violation: 1242 Subquery returns more than 1 row
I had this error running this code:
$query = $this->createQueryBuilder('s')
->select('
s.name,
s.date,
(SELECT p.nom FROM '.Participant::class.' p WHERE p.session = s.id) participants
')
->getQuery()->getArrayResult();
I know I could just fetch my sessions, then loop through them and fetch their participants with another DQL query, but obviously that doesn't seem like the proper way to do it. Is there a better way?
You can directly do a leftJoin on your QueryBuilder :
$queryResult = $this->createQueryBuilder('s')
// After that next line, you can reference participants as 'p'
->leftJoin('s.participants', 'p')
// If you intend to loop on the result, to avoid the N+1 problem, add this line :
->addSelect('p')
->getQuery()
->getResult()
;

How to join results from with operator in Laravel?

I use query builder for execution inquiries to db like as:
$result = Order::with("product", "images");
As result I get response with two nested objects inside:
{["product" : [{}], "images" : [{}]]}
How can I join these two objects to one, that to get the following response:
{"title" : "Product name", "price" : 3, "images" :{}, "order" : {} }
You should use nested eager loading here:
Order::with('products.images')->first();
If you want to get an array or JSON instead of collection, use toArray() or toJson() methods on collection.

Display parent-child relation yii2

I am looking for some way to implement the following thing with yii2:
Lets imagine we have the following structure:
- authors table.
- Books table
Each author -> has written 1 or more books.
What I want to do is to display on a view, the details of an author, and under it, a gridview of all the books it has written. After that, control buttons to create/ remove new books for that current author, along with a gridview of the books which belongs to the current author... In some other words, a master-detail view.
How I should retrieve the data of the books? From the same controller for Authors?
I have already implemented the table relations between authors and books, in the Author's model
Thanks in advance, any help is welcome!!
If the you have the following relation in your Author model:
public function getBooks()
{
return $this->hasMany(Books::className(), ['author_id' => 'id']);
}
After declaring relations, getting relational data is as easy as accessing a component property that is defined by the corresponding getter method:
$author = Author::findOne(1);
$books = $author->books;
http://www.yiiframework.com/doc-2.0/guide-db-active-record.html
The solution I found at the end was to :
On the Author's controller, I modified the "view" action, so I could a "books" activeDataprovider, and then filtering it by "author id":
public function actionView($id)
{
//get current author
$author=$this->findModel($id);
$books_search = new BookSearch();
//get the related books for current author
$written_books = $books_search->search(['bookSearch'=>['id_author'=>$id]]);
return $this->render('view', [
'author' => $author,
'books_search'=> $books_search,
'books'=>$written_books,
]);
}
Then I could create on the Author's view, a gridview with the books written by the current author

How do I return a hash with relational data using parse.com?

I have a Post class and I want to get the products associated to it. I'd like to write a single query that fetches all of the posts with the products associated to them. Below is a rough idea of what I'd like the hash to looks like.
Schema:
Post - objectId, title
PostItem - post(pointer), product(pointer)
Product - objectId, title, price
Output I want
{'results':
[{'objectId':'blah', 'title':'The Post',
'products':
[{'objectId':'14',
'title':'First product',
'price':'20'
},
{'objectId':'26',
'title':'Second product',
'price':'55'
}]
},
{'objectId':'blah2', 'title':'Second post',
[{'objectId':'38',
'title':'Some product',
'price':'54'
},
{'objectId':'26',
'title':'Another Product',
'price':'88'
}]
}]
}
Is this possible to do in one query? How would I do this using curl and parse.com?
If this is a many-to-many relationship, use a Parse relationship.
You'll want to use the include key option alongside pointers. Since it's been nearly a year since you posted, I assume you figured it out, but lurkers can read more about this (in Javascript) here.

LINQ query for tag system: Matching any of several tags?

I am just getting started with LINQ. I am creating an Entity Framework app that uses the canonical Post and Tag model. A Post contains an ID, Text, and Tags, and a Tag contains an ID, a Name, and Posts.
A previous thread on StackOverflow showed me how to query for a Post that matches all Tag objects (A and B and C) in a search list. But how would I query for a Post that matches any Tag (A or B or C) in the list? Thanks for your help.
Stumbled over the answer right after I posted this question. PredicateBuilder to the rescue!
Here's my code, which uses PredicateBuilder. It is set up as an extension method:
public static IQueryable<Note> WhereContainsAnyTags(this IQueryable<Note> notes, IEnumerable<Tag> searchTags)
{
// Initialize
var predicate = PredicateBuilder.False<Note>();
// Select Notes that contain any search Tags
foreach (var searchTag in searchTags)
{
var tag = searchTag;
predicate = predicate.Or(note => note.Tags.Any(t => t.Id == tag.Id));
}
// Set return value
return notes.AsExpandable().Where(predicate);
}
And here is how I call the code:
searchResults = m_ViewModel.ObjectContext.Notes.WhereContainsAnyTags(m_ViewModel.SearchTags);
Not sure if this would work or not, but worth a try anyway I guess if you are already using WhereIn.
var posts = context.Tags.WhereIn(tag => tag.Name, acceptableValues)
.SelectMany(t => t.Posts);
The WhereIn should give you all the tags that are part of the name, and the SelectMany should give you all the posts containing those tags.
You could aslo do it like this with Entity SQL
var post = ctx.Posts.Where("it.Tags.Id IN (1,2,3)");

Resources