Drupal 8 entity query with multiple taxonomy terms - drupal

I have a Drupal 8 content entity with a relation to a taxonomy term which allows multiple values.
I want to query the entity and get content that has only the terms I use in the query.
The problem is I could not find a way to query my entity with multiple taxonomy terms and get the content that are associated with them.
My content entity (node bundle) is called "cocktails" and has among others an entity reference field called "field_ingredients" that has a relation to the taxonomy Vocabulary "Ingredients".
I want to get the entity that has for example 2 ingredients with the taxonomy ids: 40 AND 35. I tried the following code without success:
$query = \Drupal::entityQuery('node');
$query->condition('type', 'cocktails');
$query->condition('field_ingredients.entity.tid', 40);
$query->condition('field_ingredients.entity.tid', 35);
$node_ids = $query->execute();
$node_ids are 0
And also this:
$query = \Drupal::entityQuery('node');
$query->condition('type', 'cocktails');
$query->condition('field_ingredients.entity.tid', array(40, 35), 'IN');
$node_ids = $query->execute();
$node_ids are 3 which returns the node ids that have one of the two taxonomy ids (OR logic),
The right answer should be one node id, which is the node that is related to both taxonomy ids, the cocktail with both ingredients

Finally the solution was posted in the actual Drupal API Documentation as a comment
$query->condition(
$query
->andConditionGroup()
->condition('field_ingredients', [40, 35,])
)
);
look at the following link for more details:
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Entity!Query!QueryInterface.php/function/QueryInterface%3A%3AandConditionGroup/8.2.x
on the first comment and first example ("WORKING code")

Related

How can I count the instances of a custom taxonomy term in the scope of a custom post type?

I have a custom taxonomy called "tasks" shared between two custom post types of "roles" and "products".
Expected results:
I need to count how many times a given "task" term is used for each "role" post type minus the count shared by a "product" post type using the same "task" term.
Actual results:
None to report as I don't know how to tackle this
Error messages:
None
What I've tried:
Google keeps coming back with how to count the post type, not the terms :(
The code below is my plan B. Here I am just doing some micro loops on each post-type (only one shown below for brevity), getting the tasks and turning them into an associative array via array_count_values
$taskList = [];
$queryRoles = new WP_Query( array(
"post_type" => "roles"
));
while ( $queryRoles->have_posts() ) : $queryRoles->the_post();
$tasks = get_the_terms( get_the_ID(), "tasks" );
foreach ( $tasks as $task ) :
$taskList[] = $task->name;
endforeach;
endwhile;
$overlappingRoleTasks = $taskList;
print_r(array_count_values($taskList));
you could do a loop restricted to only posts with tasks assigned and one restricted to only products with assigned tasks.
Then using sizeof(); which return the number of elements in an array, count each number of posts and products and then do some basic php maths.
More about sizeof(); # https://www.w3schools.com/php/func_array_sizeof.asp

Symfony ManyToMany - Inquiry that retrieves all product attributes that belong to a given category

I have a problem with the query in many-to-many relationship.
I have a category table that has many-to-many relationships with the Products table, and the Products table has one-to-many relationships with the attributes category (one product can have many attributes). I want to do a query that will return all attributes of products in a given category to me, if any products are assigned to a given category then I want to download their attributes.
It seems to me that I should download records from the Attributes table repository, ie $this -> getDoctrine-> getRespitory (Attribute :: class) -> getAllProductsAttributeInCategory ($ categoryId); and discard records with the andWhere function. I am interested in the Id, name and value from this table, but how can I check if the product of a given attribute is in a given category with many-to-many relation?
I perform the function in AttributeRepository:
public function getAllProductsAttributeInCategory($categoryId)
{
return $this->createQueryBuilder('attr')
->addSelect('attr')
->innerJoin('attr.product', 'product') // Product table
->addSelect('product')
->andWhere('product.categories IN (:id)')->setParameter('id', $categoryId)
->orderBy('a.name', 'ASC')
->getQuery();
}
You can check if a product is in a specific category by joining on this specific category. Something like this:
return $this->createQueryBuilder('attr')
->join('attr.product', 'product')
->join('product.categories', 'category', Join::WITH, 'category.id = :cateogryId')
->setParameter('categoryId', $categoryId)
->orderBy('attr.name')
->getQuery()
;

How can i select extra fields and map them to entity via doctrine query builder in symfony?

I have two entities: Category and Product. Category entity has not link to Product (protected $products // ArrayColection). I need to calculate total amount of product prices inside each category, and i need to do it ONLY IN SINGLE request via query builder.
Can i do something like this:
$categories = $categoryRepository->createQueryBuilder('c')->join('AppBundle:Product', 'p')->addSelect('SUM(p.price) as c.totalPrice')->addGroupBy('c.id')->getQuery()->getResults();
And then map attribute totalPrice to entity, to have access to it somehow like this:
$categories->get(0)->totalAmount
I CAN'T build extra query, and i CAN'T add relationsip field to Category ($products) to calculte totalSum in entity method by adding price of each product. I should done it only with single query...
What you are talking about is possible with Doctrine > 2.4
Check out their docs for more details on joins: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html
Meanwhile - this is what should work for you:
$query = $this->createQueryBuilder('c')
->leftJoin('AppBundle:Product', 'p', 'WITH', 'p.category = c.id')
->select('SUM(p.price) as totalPrice')
->groupBy('c.id');
Note how we use the leftJoin method parameters - this is what allows you to run the query despite there is no relation between tables.
Hope that works for you

Wordpress - template category give me two catogories instead of one

I use the category template for categories. In this template, I use the function get_the_category() at the beginning for show the selected category in a list.
For most of my categories, I don't have any problems, but for two of them (ID 9 and ID 152), on their respective pages, the function give me two categories instead of one (the 9 and the 152).
Have you any idea to resolve this problem ?
This is the proper behavior of get_the_category():
Return: (array) Array of objects, one for each category assigned to the post.
If you need to target only one, you can target the first element of the array, like any other array:
$cats = get_the_category(); // Get all of the categories
$cat = $cats[0]; // Get one category

How to use multiple filters to widen the search in Apachesolr queries

Making a search with Apachesolr, i want to add a couple of filters in hook_apachesolr_prepare_query(&$query). This works fine, except I want the filters to widen the search ('OR'), rather than narrow it ('AND').
For example, if I have 4 nodes of type:A and 3 of type:B that match a search, to filter by type:A and type:B should return 7 nodes (of type:A AND nodes of type:B), rather than 0 those of type:A which are also of type:B.
I saw a suggestion to do this using the model of nodeaccess
foreach ($filters as $filter) {
$subquery = apachesolr_drupal_query();
if (!empty($subquery)) {
$subquery->add_filter('type', $filter);
$query->add_subquery($subquery);
}
}
but this doesn't seem to work. (It doesn't return any results).
I then tried (as I have a limited number of node types) excluding the types that I don't want:
$excludes = array('A', 'B', 'C');
$excludes = array_diff($excludes, $filters);
$exclude = implode('&', $excludes);
$query->add_filter('type', $exclude, TRUE);
This method of stitching them together doesn't work (the '&' gets escaped) but neither does adding them as subqueries, similar to the manner above.
Any suggestions on how to do this?
With Drupal7 and the last apacheSolr API, you can do OR filters by doing this :
function my_module_apachesolr_query_alter($query) {
// first, create a subQuery filter to store others
// and specify there is a "OR" condition
$filter = new SolrFilterSubQuery('OR');
// next, add all filters on bundle you want, each as
// a new subQuery filter, always with "OR" condition
// and add it to the primary filter
$a = new SolrFilterSubQuery('OR');
$a->addFilter('bundle', 'A');
$filter->addFilterSubQuery( $a );
$b = new SolrFilterSubQuery('OR');
$b->addFilter('bundle', 'B');
$filter->addFilterSubQuery( $b );
$c = new SolrFilterSubQuery('OR');
$c->addFilter('bundle', 'C');
$filter->addFilterSubQuery( $c );
// finally, add the primary subQuery filter as
// subquery of the current query
$query->addFilterSubQuery( $filter );
}
And your query search about type A OR type B OR type C (all results in each types). You can combine OR / AND by changing the parameter of the SolrFilterSubQuery instanciation.
Special thanks to this page and it's author : http://fr.ench.info/blog/2012/04/03/Add-Filters-ApacheSOLR.html
I havenť played with SOLR much but I am quiete familiar with Drupal and Zend Lucene (or Drupal Lucene API).
I would suggest that you try to filter your results based on content type (because each node has its content type stored in the object).
The second idea is to change basic operator. I am not sure how it is done in SOLR but i Zend Lucene
Zend_Search_Lucene_Search_QueryParser::setDefaultOperator($operator) and Zend_Search_Lucene_Search_QueryParser::getDefaultOperator() methods, respectively.
Docs can be found in Zend Lucene Docs. Or for SOLR Solr Docs.
I hope a got your problem right.
Hope it helps :-)

Resources