Mongodb-odm: Querying field with case insensitive indexes

Created on 19 Jul 2017  路  6Comments  路  Source: doctrine/mongodb-odm

I need to query like this:

db.MyCollection.find({myField: 'Some Value'}).collation({locale: 'en', strength:1})

I guess "Collation" is not implemented yet for query in ODM. Is there any way to pass them directly to driver?

Easy Pick Feature Hacktoberfest

Most helpful comment

Issue is resolved since v2 release, all collation options are passing to driver methods.

<?php

namespace App\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;

/**
 * @MongoDB\Document(collection="Dummy")
 */
class DummyDocument
{
    /** @MongoDB\Id */
    public $id;

    /**
     * @MongoDB\Field(type="string")
     * @MongoDB\Index(
     *     options={
     *         "collation"={
     *             "locale"="en",
     *             "strength"=2
     *         }
     *     }
     * )
     */
    public $firstName;

    /**
     * @MongoDB\Field(type="string")
     */
    public $lastName;
}

$qb = $this->documentManager->createQueryBuilder(DummyDocument::class);
$qb->select(['firstName', 'lastName']);
$qb->field('firstName')->equals('john');
$output = $qb->getQuery(['collation' => ['locale' => 'en', 'strength' => 2]])->execute()->toArray();

dump($output);

/*
 * array:1 [
 *    0 => App\Document\DummyDocument^ {#156
 *      +id: "5ed371d9be313ef3e086d678"
 *      +firstName: "jOhN"
 *      +lastName: "Doe"
 *    }
 * ]
 */

All 6 comments

You are correct, collation is not available in ODM yet. Looking at the legacy code, I'm not sure the legacy driver would even support passing a collection. From what I can see there is no cursor flag for it (which you may set using MongoCursor::setFlag), so you're out of luck.

The only other option would be to manually issue a find command using the command method in the database object. You'll return a cursor and would have to manually wrap it to get hydrated data.

Thanks @alcaeus. So any plan to implement it? Can I use alcaeus/mongo-php-adapter to pass collation?

mongo-php-adapter is designed to simulate the legacy API, so I don't think you'll be able to pass it there either.

Yes, we're planning to implement it, it will have to wait until 2.0 though (which will use the new driver).

Okay, I will wait for 2.0. :)
For now I think I should set default collation in the collection itself which query will use automatically. I am not sure if it would use default collation for all queries or only with fields participating in the case-insensitive index.

@metanav: Another work-around may be to create an index with the desired collation and then rely on the hint query option to utilize that index. That may be preferable in the event that the collation isn't something you want for all queries on the collection.

Issue is resolved since v2 release, all collation options are passing to driver methods.

<?php

namespace App\Document;

use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;

/**
 * @MongoDB\Document(collection="Dummy")
 */
class DummyDocument
{
    /** @MongoDB\Id */
    public $id;

    /**
     * @MongoDB\Field(type="string")
     * @MongoDB\Index(
     *     options={
     *         "collation"={
     *             "locale"="en",
     *             "strength"=2
     *         }
     *     }
     * )
     */
    public $firstName;

    /**
     * @MongoDB\Field(type="string")
     */
    public $lastName;
}

$qb = $this->documentManager->createQueryBuilder(DummyDocument::class);
$qb->select(['firstName', 'lastName']);
$qb->field('firstName')->equals('john');
$output = $qb->getQuery(['collation' => ['locale' => 'en', 'strength' => 2]])->execute()->toArray();

dump($output);

/*
 * array:1 [
 *    0 => App\Document\DummyDocument^ {#156
 *      +id: "5ed371d9be313ef3e086d678"
 *      +firstName: "jOhN"
 *      +lastName: "Doe"
 *    }
 * ]
 */
Was this page helpful?
0 / 5 - 0 ratings