Querying: Intersection
-
To allow users to
intersect
queries on the server-side and return only documents that match all the provided sub-queries, we introduced the query intersection feature. -
In this page:
Intersection
Let's consider a case where we have a T-Shirt class:
class TShirt
{
private ?string $id = null;
private ?int $releaseYear = null;
private ?string $manufacturer = null;
private ?TShirtTypeList $types = null;
public function getId(): ?string
{
return $this->id;
}
public function setId(?string $id): void
{
$this->id = $id;
}
public function getReleaseYear(): ?int
{
return $this->releaseYear;
}
public function setReleaseYear(?int $releaseYear): void
{
$this->releaseYear = $releaseYear;
}
public function getManufacturer(): ?string
{
return $this->manufacturer;
}
public function setManufacturer(?string $manufacturer): void
{
$this->manufacturer = $manufacturer;
}
public function getTypes(): ?TShirtTypeList
{
return $this->types;
}
public function setTypes(?TShirtTypeList $types): void
{
$this->types = $types;
}
}
class TShirtType
{
private ?string $color = null;
private ?string $size = null;
public function __construct(?string $color, ?string $size)
{
$this->color = $color;
$this->size = $size;
}
public function getColor(): ?string
{
return $this->color;
}
public function setColor(?string $color): void
{
$this->color = $color;
}
public function getSize(): ?string
{
return $this->size;
}
public function setSize(?string $size): void
{
$this->size = $size;
}
}
class TShirtTypeList extends TypedList
{
protected function __construct()
{
parent::__construct(TShirtType::class);
}
}
We will fill our database with a few records:
// first tShirt
$tShirt = new TShirt();
$tShirt->setId("tshirts/1");
$tShirt->setManufacturer("Raven");
$tShirt->setReleaseYear(2010);
$types = TShirtTypeList::fromArray([
new TShirtType(color: "Blue", size: "Small"),
new TShirtType(color: "Black", size: "Small"),
new TShirtType(color: "Black", size: "Medium"),
new TShirtType(color: "Gray", size: "Large")
]);
$tShirt->setTypes($types);
$session->store($tShirt);
// second tShirt
$tShirt = new TShirt();
$tShirt->setId("tshirts/2");
$tShirt->setManufacturer("Wolf");
$tShirt->setReleaseYear(2011);
$types = TShirtTypeList::fromArray([
new TShirtType(color: "Blue", size: "Small"),
new TShirtType(color: "Black", size: "Large"),
new TShirtType(color: "Black", size: "Medium")
]);
$tShirt->setTypes($types);
$session->store($tShirt);
// third tShirt
$tShirt = new TShirt();
$tShirt->setId("tshirts/3");
$tShirt->setManufacturer("Raven");
$tShirt->setReleaseYear(2011);
$types = TShirtTypeList::fromArray([
new TShirtType(color: "Yellow", size: "Small"),
new TShirtType(color: "Gray", size: "Large")
]);
$tShirt->setTypes($types);
$session->store($tShirt);
// fourth tShirt
$tShirt = new TShirt();
$tShirt->setId("tshirts/4");
$tShirt->setManufacturer("Raven");
$tShirt->setReleaseYear(2012);
$types = TShirtTypeList::fromArray([
new TShirtType(color: "Blue", size: "Small"),
new TShirtType(color: "Gray", size: "Large")
]);
$tShirt->setTypes($types);
$session->store($tShirt);
Now we can use the intersect
method to return all the T-shirts that are
manufactured by Raven
and contain both Small Blue
and Large Gray
types.
/** @var array<TShirt> $results */
$results = $session->query(TShirts_ByManufacturerColorSizeAndReleaseYear_Result::class, TShirts_ByManufacturerColorSizeAndReleaseYear::class)
->whereEquals("Manufacturer", "Raven")
->intersect()
->whereEquals("Color", "Blue")
->andAlso()
->whereEquals("Size", "Small")
->intersect()
->whereEquals("Color", "Gray")
->andAlso()
->whereEquals("Size", "Large")
->ofType(TShirt::class)
->toList();
class TShirts_ByManufacturerColorSizeAndReleaseYear_Result
{
private ?string $manufacturer = null;
private ?string $color = null;
private ?string $size = null;
private ?int $releaseYear = null;
// ... getters and setters
}
class TShirts_ByManufacturerColorSizeAndReleaseYear extends AbstractIndexCreationTask
{
public function __construct()
{
parent::__construct();
$this->map = "docs.TShirts.SelectMany(tshirt => tshirt.types, (tshirt, type) => new {" .
" manufacturer = tshirt.manufacturer," .
" color = type.color," .
" size = type.size," .
" releaseYear = tshirt.releaseYear" .
"})";
}
}
from index 'TShirts/ByManufacturerColorSizeAndReleaseYear'
where intersect(Manufacturer = 'Raven', Color = 'Blue' and Size = 'Small', Color = 'Gray' and Size = 'Large')
The above query will return tshirts/1
and tshirts/4
, that match all sub-queries.
tshirts/2
will not be included in the results because it is not manufactured by Raven
,
and tshirts/3
will not be included because it is not available in Small Blue
.