I have the following entity:
This is an example query:
$list = 'My List';
$query->filter('isUnsubscribed.'.$list, '=', '0');
$query->filter('methodAdded.'.$list, '=', 'Import');
$query->filter('dateAdded.'.$list, '<', '13.01.2018');
And here is the problem:
Everything is working fine if my index is:
- kind: Contacts
ancestor: yes
properties:
- name: isUnsubscribed.My List
- name: methodAdded.My List
- name: dateAdded.My List
But I cannot create index for every list, because the users can create their own lists. So I tried with this index, but it is not working:
- kind: Contacts
ancestor: yes
properties:
- name: isUnsubscribed
- name: methodAdded
- name: dateAdded
Is there a way to create the index without specifying the properties in the embedded entity, maybe a wildcard or something else?
There isn't a way to query user data stored in property names (this includes embedded property names too). Always structure your data so that variable data ends up as values, there as well known (by the programmer) data is the kind/property names.
In your example, have isUnsubscribed as a repeated property (array) of lists users have unsubscribed from - all the ones you currently have as 0 values. You can have a second list isSubscribed for everything that has 1.
Related
This is driving me crazy. I've been all over documentation and StackOverflow and other places trying to figure out how to just get Symfony or Sonata to behave sensibly with a form field empty value default or override.
OK, say you have a form that relates to an ORM entity that saves to its own MySQL database table, and that form has a field that when empty you want to default to 0 (integer or string, it doesn't matter).
On a New form, setting FormMapper ->add 'empty_data' => '0' works fine (I use string zero because the value saves as VARCHAR), however, on an Update (or Edit) form, the existing record's value always shows as empty (nothing in the field), whether that saved value is NULL or '' (empty string). If the value is already 0, it shows 0.
Example:
TheThing.orm.yml:
theThing:
nullable: false # originally true
options: # originally not specified because NULL was default
default: 0 # saves as string in VARCHAR column
With this config, running bin/console doctrine:schema:update --force updates table the_thing, changing the NULL values to empty string. Not good database practice, but I'll do what I have to to make this work with Symfony/Sonata/Doctrine/whatever.
Entity TheThing:
private $theThing = '0';
Normal getter and setter. Everything works as expected on a New form, the value defaults to 0.
The FormMatter field definition:
->add('theThing', 'text', [
'label' => 'The Thing Field',
// TODO: If database value is NULL or empty, set value to 0.
'empty_data' => '0', // this doesn't work on the Update form if the saved value is NULL or empty string
//'empty_value' => '0', // suggested but apparently deprecated and invalid
//'data' => '0', // hard-sets the value; overrides existing value no matter what
])
So, my solution is to either figure out how to get Symfony to understand that I want empty values (NULL, empty string) to show a default/override that I specify (like 0), or I modify the existing records to convert empty values to 0.
Do I need to do the bad database practice thing, or is there a Symfony/Sonata/Doctrine solution that get the form Update/Edit field to behave sensibly?
PS I'm using Symfony 3, Sonata 3, and Doctrine 1. Sorry, I have to until we can upgrade. Your solution may still be viable however, or a good hint.
I have the following basic test entities:
#Entity()
class Author {
#PrimaryKey()
public id!: number;
#Property()
public name!: string;
}
#Entity()
class Book {
#PrimaryKey()
public id!: number;
#Property()
public title!: string;
#ManyToOne({joinColumn: 'authorID'})
public author!: Author;
}
What i'm trying, is to select only a single Book record, with its 'author', but I care only about its ID, I don't want to actually load the entity.
If I simply call this, it won't work (no author data loaded at all):
em.getRepository(Book).findOne({id: 1}, {fields: ['id', 'title', 'author.id']});
'author.id' doesn't do the trick, the SQL doesn't even contain the 'authorID' field.
If I add 'author' to the fields list as well, it works, author is loaded (only with the ID), but as a separate entity, with a separate, additional SQL statement! That's what I'm trying to avoid.
em.getRepository(Book).findOne({id: 1}, {fields: ['id', 'title', 'author', 'author.id']})
#1. SQL
select `b0`.`id`, `b0`.`title`, `b0`.`authorID` from `book` as `b0` where `b0`.`id` = 1 limit 1
#2. SQL (this wouldn't be neccessary as I want only the ID)
select `a0`.`id` from `author` as `a0` where `a0`.`id` in (2)
--> Result:
Book: { id: 1, title: 'a book', author: { id: 2 } }
The only way I found is to add the specific 'authorID' field too to the Book entity:
#Property()
public authorID!: number;
But, I'd like to avoid introducing these foreign key columns, it would be better to handle through the already existing and used 'author' relation (only by the 'id' property).
Does any solution exists where I could retrieve a relation's ID without generating a 2nd SELECT statement (for the relation), and even avoid introducing the foreign key (next to the already existing relation property)? Would be great to receive through the relation without any extra sql statement.
Thanks in advance.
It is correct behaviour you see the second query, that is how population works, and the fact that you want just a single property from the entity does not change anything, you still populate the relation, and each relation will use its own query to load it. You can use LoadStrategy.JOINED if you want to use a single query. But that would still do a join for that relation, which is not needed for your use case.
Given you only want the FK to be present, you dont need to care about the target entity at all. This should do the trick too:
em.getRepository(Book).findOne(1, {
fields: ['id', 'title', 'author'],
populate: [],
});
This way you say you want those 3 properties to be part of what's selected from the Book entity. You already have the author property, which represents the FK. You will end up with what you want once you serialize such entity. During runtime, you will see entity reference there - an entity with just the PK. It is represented as Ref<Author> when you console.log such entity.
Note that you need that populate: [] there, as otherwise it would be inferred from your fields which contains author property, and that would trigger the full load of it.
currently I'm using sonata admin bundle to export a "order" data, how can I export the data with manytomany relationship? I saw a post, it helps a bit, but I still not sure how to get the data in many to many relationship.
Here is my code:
public function getExportFields() {
return [
$this->getTranslator()->trans('Order Number') => 'id',
$this->getTranslator()->trans('First Name') => 'customer.First_name',
$this->getTranslator()->trans('Last Name') => 'customer.Last_name',
...]
Here is fine, but when I try to get 'OrderToProduct' or 'product.name' it failed or only output empty string. I spent to much time on this already, hope someone can give a clue. Thank you.
Well, you can't use product.name, because product is a collection.
Export action iterates through objects and get properties with path defined and tries to stringify them.
What you need to do is a workaround - define some method in Order class - i.e. getProductsAsString(), make it return string you need, and then add
$this->getTranslator()->trans('Products') => 'productsAsString'
But still - it will put whole string in single cell of xls, csv, xml you are trying to export.
I'm attempting to create an autocomplete search using Elastica and Elastic Search (more specifically, FOSElasticaBundle for Symfony2).
I've created a simple index, populated it with objects.
A basic search works, ie:
$finder = $this->container->get('fos_elastica.finder.search.person');
$results = $finder->find('Mike');
I'm having some trouble getting my prefix query to work though and I can't find any examples online. Here's what I'm trying:
$finder = $this->container->get('fos_elastica.finder.search.person');
$prefixQuery = new \Elastica\Query\Prefix();
$prefixQuery->setPrefix('nameFirst','Mik');
$results = $finder->find($prefixQuery);
It doesn't kick any errors, but just doesn't return any results.
The field should be set properly...my configuration looks like this:
...
types:
person:
mappings:
nameFirst: { boost: 10 }
nameLast: { boost: 10 }
nameMiddle: { boost: 3 }
...
Can anyone tell what I'm doing wrong?
Also: Bonus Question: Is the best way to search the prefix on both the nameFirst AND nameLast fields going to be using a NestedQuery, or using addParam() to add both the nameFirst and nameLast?
Thanks a bunch-
I want to access a query result in twig as a whole object. In the query however, I want to select just several fields from the tables + count. In my example I have a company, which is owned by an owner and has several employees. I want to create a query, which gives me a list of companies ordered by count of their employees.
$qb = $this->createQueryBuilder('c');
$qb->select('count(e.id), partial c.{id, name}, partial o.{id, name}');
$qb->leftJoin('c.employees', 'e');
$qb->innerJoin('c.owner', 'o');
$qb->groupBy('c.id');
The query works fine, however I get an error, when I want to access other objects liked with normaly in the company entity (there is an collection of image entities, and each image entity contains the path to the image). The query does not load the whole company entity with its dependencies... I cannot acces the "firstImage" method, which returns the first image from the collection. I get this error
Key "firstImage" for array with keys "0, 1" does not exist in
MyBundle:List:results.html.twig at line 6
Note that leaving out the "employees count" makes it whole work.
$qb = $this->createQueryBuilder('c');
$qb->select('partial c.{id, name}, partial o.{id, name}');
$qb->leftJoin('c.employees', 'e');
$qb->innerJoin('c.owner', 'o');
$qb->groupBy('c.id');
Your object will be the first element of result array and the count() value will be the second. You can access to object properties and methods in twig by the following way:
{{ object[0].firstImage }}
{{ object[0].name }}
And the count of employees can be accessed as:
{{ object[1] }}
Also you may define the name for your count() value in the query
$qb->select('count(e.id) AS empQty, partial c.{id, name}, partial o.{id, name}');
and then you can access this value in twig as:
{{ object['empQty'] }}