Laravel Eloquent distinct values - eloquent

PROBLEM SOLVED.
I'm trying to get an person's books, but there are more than one book in my book table since there are different editions of a book. When I list all books of a person, I shouldn't list duplicates.
Here's what I've done so far
Person Model
public function books() {
return $this->belongsToMany('\App\Models\Thing', 'bookxauthor', 'person_id', 'thing_id');
}
PersonController.php
$allbooks = Person::find($id)->books;
This is great, it lists all the books of an author, but I don't need duplicates.
The query below works. type_id means it's a book.
$findBooks = Person::with(array('books' => function($query)
{
$query->where('type_id',"=",3)->groupBy('original_name');
}))->find($id);
$allbooks = $findBooks->books;

You could use the groupBy function for collections
Eg.
$allbooks = Person::find($id)->books->groupBy('name')->get();

The query below works.
$findBooks = Person::with(array('books' => function($query)
{
$query->where('type_id',"=",3)->groupBy('original_name');
}))->find($id);
$allbooks = $findBooks->books;

Related

How to query all the owned objects in one query MTM?

I have a list of the owning side of a many-to-many relationship. How do I query all the owned objects in one query using Grails GORM? In SQL I would used the join table and the owned table and the ids for the owning table with an in clause.
Example domain classes:
class Book {
static belongsTo = Author
static hasMany = [authors:Author]
String title
}
class Author {
static hasMany = [books:Book]
String name
}
So I have a List or Set of Authors and I want to find all their Books in one query.
select b.*
from book b
join author_book ab on b.id = ab.book_id
where ab.author_id in (1, 2, 3);
In Grails I tried the following but it fails.
def books = Book.withCriteria {
inList('authors', authors)
}
You need to join the author first:
def books = Book.withCriteria {
authors {
inList('id', authors*.id)
}
}
Is this what you're looking for?
Book.findAllByAuthorInList(authors)

Laravel Mongo GroupBy And count in an efficient manner

I have an authors collection that has a many-to-many relation to a posts collection. The posts collection has a category field which can be, for example, "Suspense", "Drama", "Action", etc.
I need to go through my entire posts collection and group by the category fields and also have the associated counts.
This is what I have so far:
$authors = Author::where('active', true)->get();
foreach ($authors as $author){
foreach ($author->posts()->groupBy('category')->get() as $data){
// Do some logic
}
}
Basically the output I am expecting is an array with category as keys and the counts as a value. So if I do $a['Drama'] it gives me count of how many times that author wrote a post with that category.
I can probably figure it out by working in my loop logic above but it does not look very efficient. Should I look at aggregation? If so can someone get me started?
Try this:
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
$authors = DB::collection('authors')
->where('active', true)
->get();
// Laravel >= 5.3 would return collection instead of plain array
$authors = is_array($authors) ? Collection::make($authors) : $authors;
$authors->map(function ($author) {
return $author
->posts()
->groupBy('category')
->get()
->map(function ($collection) {
return $collection->count();
});
});

Using IQueryable with and without AsQueryable()

I would like to know what happens when I use IQueryable with and without AsQueryable(). Here is an example:
public partial class Book
{
.......
public Nullable<System.DateTime> CheckoutDate{get; set;}
}
I need to filter the data from SQL server before it is returned to an application server. I need to return books checked out more recently than entered date. Which one should I use?
A.
IQueryable<Book> books = db.Books;
books = books.Where(b => b.CheckoutDate >= date);
B.
IQueryable<Book> books = db.Books.ToList().AsQueryable();
books = books.Where(b => b.CheckoutDate >= date);
Basically I would like to know what is the difference between the above two options. Do they work on the similar grounds? Do they return same values?
With B option, you're basically retrieving every book from database and filtering data in memory.
A option is more performance, as it filters data at the database and return only the rows that match your query.

How to get result by joining two collections (tables) [Cakephp/MongoDB]

I am using https://github.com/ichikaway/cakephp-mongodb.git plugin for accessing mongodb datasource.
I have two Models: Teachers and Subject. I want joint find result on Teacher and Subject.
Here are my two models:
Teacher:
<?php
class Teacher extends AppModel {
public $actsAs = array('Containable');
public $hasOne = array('Subject');
public $primaryKey = '_id';
var $mongoSchema = array(
'name'=>array('type'=>'string'),
'age'=>array('type'=>'string'),
'subjectid'=>array('type'=>'string'),
'created'=>array('type'=>'datetime'),
'modified'=>array('type'=>'datetime'),
);
Subject:
<?php
class Subject extends Model {
public $actsAs = array('Containable');
public $belongsTo= array('Teacher');
public $primaryKey = '_id';
var $mongoSchema = array(
'name'=>array('type'=>'String'),
'code'=>array('type'=>'String'),
'created'=>array('type'=>'datetime'),
'modified'=>array('type'=>'datetime')
);
In Teachers Controller to get joint result, I did:
$results = $this->Teacher->find('all',array('contain'=>array('Subject')));
$this->set('results', $results);
But I am not getting any result from Subjects Collections.
Here is what I am getting:
array(5) {
[0]=>
array(1) {
["Teacher"]=>
array(7) {
["_id"]=>
string(24) "52e63d98aca7b9ca2f09d869"
["name"]=>
string(13) "Jon Doe"
["age"]=>
string(2) "51"
["subjectid"]=>
string(24) "52e63c0faca7b9272c09d869"
["modified"]=>
object(MongoDate)#78 (2) {
["sec"]=>
int(1390820760)
["usec"]=>
int(392000)
}
["created"]=>
object(MongoDate)#79 (2) {
["sec"]=>
int(1390820760)
["usec"]=>
int(392000)
}
}
}
I am a cakephp/mongoDB rookie only, Please guide me to get the desired result.
Edit: I read that mongoDb don't support Join Operation. Then How to manually do it? I mean I can write two find query on each Model, then how to combine both array and set it to view?
As you said, MongoDB does not support joins. Documents in query results come directly from the collection being queried.
In this case, I imagine you would query for Teacher documents and then iterate over all documents and query for the Subject documents by the subjectid field, storing the resulting subject document in a new property on the Teacher. I'm not familiar with this CakePHP module, but you may or may not need to wrap the subjectid string value in a MongoId object before querying. This depends on whether or not your document _id fields in MongoDB are ObjectIds or plain strings.
If Subjects only belong to a single teacher and you find that you never query for Subjects outside of the context of a Teacher, you may want to consider embedding the Subject instead of simply storing its identifier. That would remove the need to query for Subjects after the fact.

Using relationships to search in DBIx::Class

I am starting learning DBIx::Class and I have a doubt in searching in a related table:
Consider the following code:
my $books = $author->search_related('books', { name => 'Titanic' });
my $books = $author->books->search({name => 'Titanic'});
What I want is to only searches for books named 'Titanic' by the author in $author.
This two searches return the same resultset?
If yes, what is the best way and why?
If no, what is the difference?
search_related is a Resultset method. You'd use that if you had a resultset of Authors and you wanted to get a resultset of all of their books named 'Titanic'.
my $books = $schema->resultset('Author')->search({ last_name => 'Smith' })
->search_related('books', { name => 'Titanic' });
If $author is a row object, representing one row, then your second line is how you'd search his books.
my $books = $author->books->search({ name => 'Titanic' });
The distinction between rows and resultsets is one of the core concepts of DBIx::Class. You might want to review the DBIC Manual Intro. #dbix-class on irc.perl.org is usually pretty active so you can find help there as well.