I need to make a query where I can get "Place" table, but I have to exclude from that query all "Place" that are already part of the "LocationGroupPlace" table.
I have a class called Place and other called LocationGroupPlace
each LocationGroupPlace can contain many Places
these are the relations
in Place.php file
public function locationGroupPlace()
{
return $this->hasMany(LocationGroupPlace::class, 'place_id');
}
in LocationGroupPlace.php file
public function place(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Place::class);
}
I am trying to retrieve 5 items from "Place" that do not exist in "LocationGroupPlace", that is, the IDs of "Place" are not in the table of "LocationGroupPlace", for example these IDs
I'm trying to get the first 5 Place with all the table from LocationGroupPlace with a subquery (for test my subquery)
public function getUsedPlacesForGroups()
{
return Place::with(['locationGroupPlace' => function ($query){
$query->get();
}])->limit(5)->get();
}
but I can't get LocationGroupPlace, the relations section is empty
Note: locationGroupPlace is the function in Place
How can I get all LocationGroupPlace? my final idea is to exclude all "Places" included in "LocationGroupPlace"
If you want the places that doesn't exist in LocationGroupPlace then you can use doesntHave
$places= Place::doesntHave('locationGroupPlace')->limit(5)->get();
See Querying Relationship Absence
Related
We are using two objects: Employee and Company
In Employee object contains a reference to Company (idcompany). How can I get the Employee object with the Company fields too? (Using a view or search index)
Example:
employee
{
"name":"test",
"idcompany":"4a70356d1a99260f3b9fd565a10e5ece",
"objecttype":"employee"
}
company
{
"id":"4a70356d1a99260f3b9fd565a10e5ece",
"name":"test",
"objecttype":"company"
}
You can try the Join With Views proposal
You can define view with the following map function
function (doc) {
if (doc.idcompany) {
emit(doc._id, {"_id":doc.idcompany});
}
}
Then retrieve the view values using the include_docs=true param. You will get the key that you defined in the emit function, joined with the company document.
Let's assume the following Grails domains:
Owner {
String name
static hasMany [cars: Cars]
}
Car {
Date inspectionDate
}
I want to be able to search for Owners through Criteria, with the following rule: Most recent Car by inspectionDate in Owner's cars list being lower than *given date*.
As an example, I want to apply the following code to a select query in GORM:
queryResultsList = allOwnersList.filter { owner ->
owner.cars.min{ car -> car.inspectionDate }.inspectionDate < myDate
}
I need to achieve it using Criteria because I am already filtering Owners on other fields.
The whole given code is used as an example, some parts of the original code has been ommited, and source code is not about cars and owners.
As on first thought I assumed I needed a subquery in SQL to retrieve my data as I expected, I tried the following:
Owner.createCriteria().list {
// [...] some filters on other fields
cars {
lt('inspectionDate', params.inspectionDate)
'in'('inspectionDate', new grails.gorm.DetachedCriteria(Owner).list {
projections {
cars {
min('inspectionDate')
}
}
})
}
}
I also tried to add groupProperty in different places in the projection, ending with MissingPropertyException.
I am using Grails 2.2.4
After a few days testing solutions, I've come to the following one:
Owner.createCriteria().list {
// [...] some filters on other fields
cars {
lt('inspectionDate', params.inspectionDate)
'in'('inspectionDate', Owner.createCriteria().list {
projections {
cars {
min('inspectionDate')
}
groupProperty 'id'
}
// this allows to only get first property, which is inspectionDate
}.collect { it[0] })
}
}
However, I still feel like doing things wrong. In particular, the collect part looks like a code smell.
I am posting this because it does what I need, but any help with finding a good solution will be appreciated.
Assuming I have the following MySQL tables to represent pricebooks, items and the relationship between them:
item - item_id|name|...etc
pricebook - pricebook_id|name|...etc
and the following pivot table
pricebook_item - pricebook_id|item_id|price|...etc
I have the correlating Eloquent models: Pricebook, Item and a repository named PricebookData to retrieve the necessary information.
Within the PricebookData repository, I need to get the pricebook data grouped by pricebook id and then keyed by item_id for easy access on client side.
If I do:
Pricebook::all()->groupBy('pricebook_id');
I get the information grouped by the pricebook_id but inside each pricebook the keys are simple numeric index (it arrives as js array) and not the actual product_id. So when returning to client side Javascript, the result arrives as the following:
pricebookData: {1: [{}, {}, {}...], 2: [{}, {}, {}...]}
The problem with the prices arriving as array, is that I can not access it easily without iterating the array. Ideally I would be able to receive it as:
pricebookData: {1: {1001:{}, 1002: {}, 1003: {}}, 2: {1001:{}, 1002: {}, 1003: {}}}
//where 1001, 1002, 1003 are actual item ids
//with this result format, I could simply do var price = pricebookData[1][1001]
I've also tried the following but without success:
Pricebook::all()->keyBy('item_id')->groupBy('pricebook_id');
The equivalent of what I am trying to avoid is:
$prices = Pricebook::all();
$priceData = [];
foreach ($prices as $price)
{
if (!isset($priceData[$price->pricebook_id]))
{
$priceData[$price->pricebook_id] = [];
}
$priceData[$price->pricebook_id][$price->item_id] = $price;
}
return $priceData;
I am trying to find a pure elegant Eloquent/Query Builder solution.
I think what you want is
Pricebook::all()
->groupBy('pricebook_id')
->map(function ($pb) { return $pb->keyBy('item_id'); });
You first group by Pricebook, then each Pricebook subset is keyed by item_id. You were on the right track with
Pricebook::all()->keyBy('item_id')->groupBy('pricebook_id');
unfortunately, as it is implemented, the groupBy resets previous keys.
Update:
Pricebook::all()->keyBy('item_id')->groupBy('pricebook_id', true);
(groupBy second parameter $preserveKeys)
I have Orders which contain any number of items stored in the items table (so a belongsToMany relationship between the two). The items are also categorized under itemtypes. When creating or editing an order I would like to load all items, categorized by itemtype, whether or not that order has any of the items. I was able to pull that up generically using the following:
$itemtypes = \App\Itemtype::with('items')
->orderBy('id','asc')
->get();
Then I loop through:
#foreach( $itemtypes as $itemtype )
{{$itemtype->name}}
#foreach( $itemtype->items as $item )
{{$item->name}}
#endforeach
#endforeach
This gives me something like:
NICU Items
- Baby Blanket
- Beaded Baby Cuddler
Miscellaneous Items
- Fitted Sheet
- Microfiber Towel
However, when I'm accessing a specific order which has records in item_order I want to display the saved quantities (stored in the pivot table). I know one way would be to add records for all items to item_order for every order created but that seems rather inefficient.
Item.php
public function orders() {
return $this->belongsToMany('App\Order', 'item_order', 'item_id', 'order_id') -> withPivot('id','quantity','createdby_user_id','weight','cost_billed', 'calc_by_weight', 'track_units');
}
Order.php
public function items() {
return $this -> belongsToMany('App\Item', 'item_order', 'order_id', 'item_id') -> withPivot('id','quantity','quantity_received','quantity_delivered','notes', 'createdby_user_id', 'weight', 'cost_billed', 'calc_by_weight', 'track_units');
}
UPDATE
I'm on the trail to a solution. I'm converting the collection to an array, loaded up with all items, modifying the array as needed, then using array_merge to replace the items that have quantities already in item_order.
This all works great - the only issue I'm having now is that when I load the order with it's items, items have an itemtype - a categorization and I'd like to group them by that. I'm not sure how to add a groupby to a relationship. If I figure it all out i'll post the full answer then.
What would be the best way to filter records from a view based on tags in couchbase? I mean I understand that I can extract tags from the documents and use them as the keys using the map functionality in the view. But is there a way to select records from the view based on whether the record's key (which can be multiple values) contains a tag?
Example: I have a transaction that has the following tags (tag 1, tag2, tag3, tag4) and each view record (from the emit function) looks like this
emit ([tag1,tag2,tag3,tag4], null)
What I want to get is all the records that have tag2.
Thanks for any help.
Two suggestions... If the only purpose of the view is to find records with a particular tag, you could simply emit a view row for each tag.
function (doc) {
if (doc.tags) {
for(var idx in doc.tags) {
emit(doc.tags[idx], null);
}
}
}
This map function would give you rows as follows:
{"total_rows":13,"rows":[
{"id":"foo_doc_1","key":"a","value":null},
{"id":"foo_doc_3","key":"a","value":null},
{"id":"foo_doc_1","key":"b","value":null},
{"id":"foo_doc_2","key":"b","value":null},
{"id":"foo_doc_3","key":"b","value":null},
{"id":"foo_doc_1","key":"c","value":null},
{"id":"foo_doc_2","key":"c","value":null},
{"id":"foo_doc_1","key":"d","value":null},
{"id":"foo_doc_4","key":"d","value":null},
{"id":"foo_doc_4","key":"e","value":null}
]
}
When you query by key (e.g., key="a") you'll get the results for that key. If however, your concern is "give me all documents where the second tag is 'xyz'" then you could emit the index as well.
function (doc) {
if (doc.tags) {
for(var idx in doc.tags) {
emit([parseInt(idx), doc.tags[idx]], null);
}
}
}
In this example, the rows would like like:
{"total_rows":13,"rows":[
{"id":"foo_doc_1","key":[0,"a"],"value":null},
{"id":"foo_doc_3","key":[0,"a"],"value":null},
{"id":"foo_doc_2","key":[0,"b"],"value":null},
{"id":"foo_doc_4","key":[0,"d"],"value":null},
{"id":"foo_doc_1","key":[1,"b"],"value":null},
{"id":"foo_doc_3","key":[1,"b"],"value":null},
{"id":"foo_doc_2","key":[1,"c"],"value":null},
{"id":"foo_doc_4","key":[1,"e"],"value":null},
{"id":"foo_doc_1","key":[2,"c"],"value":null},
{"id":"foo_doc_4","key":[2,"f"],"value":null}
]
}
You would then query with an array key to get a key at a particular position (e.g., key=[1, "b"]).