26/03/2016 - ELASTICSEARCH, SYMFONY
Eğer veritabanı yapınızda ilişkilendirilmiş tablolar varsa ve de siz bunları elasticsearch ile sorgulamak istiyorsanız, aşağıdaki örneği kullanabilirsiniz. Bu örnek FOSElasticaBundle paketini kullanıyor.
Join sorgulamalarında performans arttırmak isterseniz, Handling Relationships sayfasını dikkatlice okumanız gerekir. Özellikle "Application-side Joins", "Denormalizing Your Data" ve "Nested Objects" alanlarına dikkat edin.
Öncelikle composer ile friendsofsymfony/elastica-bundle
. Bu yazıyı yazarken friendsofsymfony/elastica-bundle
paketi sadece elasticsearch 1.7.4 ve alt versiyonlarını destekliyordu.
Bu ayarlar One to Many (Post - Comment) join içindir.
fos_elastica:
clients:
default: { host: 127.0.0.1, port: 9203 }
indexes:
post_index:
client: default
index_name: post_%kernel.environment%
types:
post:
mappings:
id:
type: integer
index: not_analyzed
title:
type: string
analyzer: english
is_published:
type: boolean
index: not_analyzed
comment:
type: object
properties:
id:
type: integer
index: not_analyzed
message:
type: string
persistence:
driver: orm
model: Application\SearchBundle\Entity\Post
finder: ~
provider: ~
listener: ~
Eğer aynı şeyleri MongoDB ile de yapmak isterseniz, tüm yapmanız gereken "id" alanlarını "string" ve "driver" alanını da "mongodb" yapmaktır.
namespace Application\SearchBundle\Entity;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="post")
*/
class Post
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(name="title", type="string", length=100)
*/
private $title;
/**
* @ORM\Column(name="is_published", type="boolean")
*/
private $isPublished;
/**
* @ORM\OneToMany(targetEntity="Comment", mappedBy="post", cascade={"persist", "remove"})
*/
private $comment;
}
namespace Application\SearchBundle\Entity;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="comment")
*/
class Comment
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(name="message", type="text")
*/
private $message;
/**
* @ORM\ManyToOne(targetEntity="Post", inversedBy="comment")
* @ORM\JoinColumn(name="post_id", referencedColumnName="id", onDelete="CASCADE", nullable=false)
*/
private $post;
}
Varsayalım ki "post.title" alanında "Eltit" ve "comment.message" alanında "inanzzz" araması yapıyoruz.
return $this
->createQueryBuilder('p')
->select('p, c')
->innerJoin('p.comment', 'c')
->where('p.title LIKE :title')
->andWhere('c.message LIKE :message')
->setParameter('title', '%Eltit%')
->setParameter('message', '%inanzzz%')
->getQuery()
->getResult();
SELECT *
FROM post
INNER JOIN comment ON post.id = comment.post_id
WHERE
MATCH(`post`.`title`) AGAINST ('Eltit' IN BOOLEAN MODE) AND
MATCH(`comment`.`message`) AGAINST ('inanzzz' IN BOOLEAN MODE)
#GROUP BY post.id #This would return same amount of records as doctrine and ES
curl -XGET "http://127.0.0.1:9203/_search?post_dev" -d'
{
"query": {
"bool": {
"must": [
{
"match": {
"title": "Eltit"
}
},
{
"match": {
"comment.message": "inanzzz"
}
}
]
}
},
"sort": [
{
"_score": {
"order": "desc"
}
}
],
"from": "0",
"size": "10"
}'
Varsayalım ki "post.is_published" alanında "true" ve "comment.message" alanında "inanzzz" araması yapıyoruz.
Bunu kendiniz de yapabilirsiniz.
Bunu kendiniz de yapabilirsiniz.
curl -XGET "http://127.0.0.1:9203/_search?post_dev" -d'
{
"query": {
"filtered": {
"query": {
"match": {
"comment.message": "inanzzz"
}
},
"filter": {
"bool": {
"must_not": {
"term": {
"is_published": "false"
}
}
}
}
}
},
"sort": [
{
"_score": {
"order": "desc"
}
}
],
"from": "0",
"size": "10"
}'