Eloquent: how to get values from a collection that are related to all items in a specified collection? - eloquent

I wasn't sure how to put in words of what I want to achieve so I will just demonstrate it with an example.
Let's say we have tags and objects. Tags and objects are related by a many to many relationship.
Example:
Object1 has tags A, B and C.
Object2 has tags A, D and E.
Object3 has one tag - A.
I want to get all the tags that are found across all of these objects (in this example I specified 3, but there can be N amount of objects). The result should contain a collection of tags, where only tag A would be included because that is the only tag that can be found in all 3 objects.
How may I achieve this? An example using eloquent would be perfect, thank you.

After a few hours of research I finally found what I was looking for. It's called intersection and laravel has such method for collections.
https://laravel.com/docs/7.x/collections#method-intersect
This is what I ended up with:
$tags = Tag::whereHas('objects', function($q) use($request){
return $q->whereIn('dynamic_abstract_objects.id', $request->input('objects', []));
})->get(); //first we get all the tags that belong to all provided objects
//then we iterate over each object to get it's tags
foreach($request->input('objects', []) as $objectId){
$objectTags = DynamicAbstractObject::where('id', $objectId)->first()->tags()->get();
$intersection = $objectTags->intersect($tags);
$tags = $intersection; //we assign intersection result for further loops
}
return $tags;

One way to do it would be to query the tag-to-object relationship instead. By knowning the amount of objects you have, you can check in a foreach tag loop to find how many relations it has to objects. If it matches the number of objects, it is related to all. (This is assuming each tag-to-object relation is unique, which it should).

Related

How to get distinct values from object's property with Drift (ex Moor); Flutter

TLDR: "SELECT DISTINCT category FROM items" efficiently in Drift
There is Item (or ItemsCompanion) data class that among others has 'String category' property. I'd like to get a list of distinct categories efficiently.
I'm failing to found a way
to get in result property of object without object itself
to filter out only unique values
Any help would be appreciated.
I can get a list of Items, iterate through and put it's categories in List, transform a List into a Set but it seems way too inefficient.
Using the answer from simolus3 https://stackoverflow.com/a/62359317/8108153
I got this:
Future<List<String>> getItemsCategories() {
final query = selectOnly(items, distinct: true)
..addColumns([items.category])
..where(items.category.isNotNull());
;
return query.map((row) => row.read(items.category)).get();
}
Whether it's the optimal approach or not yet it's way better anything I've come up with

Dynamics CRM + Plugin Code to Calculate Sum of fields across records and update in the another record

I have the below requirement to be implemented in a plugin code on an Entity say 'Entity A'-
Below is the data in 'Entity A'
Record 1 with field values
Price = 100
Quantity = 4
Record 2 with field values
Price = 200
Quantity = 2
I need to add the values of the fields and update it in a new record. Example shown below -
Record 3
Price = 100 + 200 = 300
Quantity = 4 + 2 = 6
Entity A has a button named "Perform Addition" and once clicked this will trigger the plugin code.
I need some ideas/pseudocode on how can i implement this. The example explained above is just a simpler version of my entity. In Real the entity has more than 60 fields on it , and for each of the fields i need to perform the sum and update in the third one. Also the number of records on which the addition would be performed can be beyond 2.
Hence more the no of records, more i will have to loop through each records and perform sum, I would like to know if there are simpler and better ways to writing this logic.
Just need guidance on how the logic should be written.
Any help would be appreciated.
Solution :
Tried the below code and it worked as suggested by the answer -
AttributeList is the list of fields i need to perform sum on. All fields are decimal
Entity EntityA = new EntityA();
EntityA.Id = new Guid({"Guid String"});
var sourceEntityDataList = service.RetrieveMultiple(new FetchExpression(fetchXml)).Entities;
foreach (var value in AttributeList)
{
EntityA[value]= sourceEntityDataList.Sum(e => e.Contains(value) ? e.GetAttributeValue<Decimal>(value) : 0);
}
service.Update(EntityA);
I recently did something similar for a client. We looked into using rollup fields, but they want the results more quickly than 12 hours.
The records containing the values that we're summing are the child records and the record containing the results is the parent.
The way it works is:
From the plugin's target entity, get the parent id.
Retrieve the parent.
Retrieve its children (via LINQ, FetchXML, or a QueryExpression).
Sum the values from the children. Since you have a lot of fields to sum, you could create a list of the field names, then use a method like this (assuming they're all Money fields)
private decimal sum(string field) => Records.Sum(b => b.GetAttributeValue<Money>(field)?.Value ?? 0);
If the fields are different types you could also create different sum methods like sumMoney, sumInt, etc. You'd then need to separate the fields by type and pass them to their appropriate method.
Populate the results on the parent Entity.
Update the parent record in Dynamics.
If the information is not that time sensitive maybe look into the out-of-box rollup fields.

Sphinx Filtering based on categories using OR

I have the following text fields I search with Sphinx: Title, Description, keywords.
However, sometimes things are narrowed down using categories. We have 3 category fields: CatID1, CatID2 and CatID3.
So, for example, I need to see if the word "Kittens" is in the Title, Description, or Keywords, but I also want to filter so that only items that have the categories (Animals - ID Number 8) or (Pets - ID Number 9) or (Felines - Category ID Number 10) in either of those CatID fields.
To clarify, only show items that have a 8,9 or 10 in CatID1, 2 or 3.
Any ideas on how I would accomplish this using sphinx filtering or searching the CatID1 fields as keywords?
Note: I am able to filter and it works great only using one category, i.e:
if(!empty($cat_str)) {
$cl->SetFilter( 'catid1', array( $cat_str ));
}
Thanks!
Craig
SetFilter takes an array. In your example you are putting $cat_str into an array. A array of one item.
So you just needs to build array with all the ids.
$cl->SetFilter( 'catid', array( $cat1, $cat2, $cat3 ));
But thats not very flexible. So you probably build the array dynamically, rather than hard-coded like that. But thats upto your application how to build the array.
But also storing the ids, in three sperate attributes, makes it hard to search. Notice in the above example, just noticed a attribute called catid. This would be a single multi-value attribute, that contains the ids from all three cat fields. That way its easy to search for ids in ANY of the columns at once.
http://sphinxsearch.com/docs/current.html#mva
if using a sql source, could do with something like
sql_query = SELECT id, title ... , CONCAT_WS(',', CatID1, CatID2 and CatID3) as catid FROM ...
sql_attr_multi = uint catid from field;

When using an extbase query, can I order the results by a field in a linked model?

I am querying a Model*, which has a field that refers to another Model. Is it possible to order the results using a field in the linked Model?
So for example:
Car contains a field which refers to its OWner. I want to show all Cars sorted by their owner.
(I don't want to use the statement() method since in that case I would have to write the whole query myself)
(*) using http://typo3.org/api/typo3cms/class_t_y_p_o3_1_1_c_m_s_1_1_extbase_1_1_persistence_1_1_generic_1_1_query.html
Yes, it is possible (don't care for the $constraint for the moment):
$query->matching($constraint)->setOrderings(
array('owner.sorting' => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING)
)->execute();
Assuming the field in you Car model is named owner and you want to sort by sorting field of the Owner model/table.
When working with 6.2
->setOrderings(Array('model.yourfield' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING))
#Michael and #rob-ot are right. There is one pitfall that took me many hours and that I'd like to mention here:
If your sort field in your related table contains underscores, you have to provide its name to setSortOrderings in lowerCamelCase:
// with database column name my_car_sorting you must define:
$query->matching($constraint)->setOrderings(
array('owner.myCarSorting' => \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING)
)->execute();

Can edges have Set of properties (by set i mean multi valued atributes)

Suppose i have a two vertexes A and B.
Can the edge between this vertices have Set of properties. By Set i mean Set. Not a map of key values.
EG Edge from A to B has Set tags.
I want model someting like A workswith B
Now workswith has properties likes ondays [monday,tuesday,friday]
tags values = ['Monday','Tuesday','Friday'];
Here tags is a single propery but its type is Set.Is it possible?
Now will traversing i would like to find something like
Find with all A works on monday?
Find will all A works on an day?
Note :This is a simple example depicting my use case .My real use case is more complex.
Yes you can. An edge is a document so can be very very complex with collections, maps and nested documents.