@@ -2676,6 +2676,22 @@ protected function buildFilters(array $queries, string $separator = '$and'): arr
26762676 */
26772677 protected function buildFilter (Query $ query ): array
26782678 {
2679+ // Normalize extended ISO 8601 datetime strings in query values to UTCDateTime
2680+ // so they can be correctly compared against datetime fields stored in MongoDB.
2681+ if (!$ this ->getSupportForAttributes () || \in_array ($ query ->getAttribute (), ['$createdAt ' , '$updatedAt ' ], true )) {
2682+ $ values = $ query ->getValues ();
2683+ foreach ($ values as $ k => $ value ) {
2684+ if (is_string ($ value ) && $ this ->isExtendedISODatetime ($ value )) {
2685+ try {
2686+ $ values [$ k ] = $ this ->toMongoDatetime ($ value );
2687+ } catch (\Throwable $ th ) {
2688+ // Leave value as-is if it cannot be parsed as a datetime
2689+ }
2690+ }
2691+ }
2692+ $ query ->setValues ($ values );
2693+ }
2694+
26792695 if ($ query ->getAttribute () === '$id ' ) {
26802696 $ query ->setAttribute ('_uid ' );
26812697 } elseif ($ query ->getAttribute () === '$sequence ' ) {
@@ -2711,7 +2727,7 @@ protected function buildFilter(Query $query): array
27112727 };
27122728
27132729 $ filter = [];
2714- if ($ query ->isObjectAttribute () && !\str_contains ($ attribute , '. ' ) && in_array ($ query ->getMethod (), [Query::TYPE_EQUAL , Query::TYPE_CONTAINS , Query::TYPE_NOT_CONTAINS , Query::TYPE_NOT_EQUAL ])) {
2730+ if ($ query ->isObjectAttribute () && !\str_contains ($ attribute , '. ' ) && in_array ($ query ->getMethod (), [Query::TYPE_EQUAL , Query::TYPE_CONTAINS , Query::TYPE_CONTAINS_ANY , Query:: TYPE_CONTAINS_ALL , Query:: TYPE_NOT_CONTAINS , Query::TYPE_NOT_EQUAL ])) {
27152731 $ this ->handleObjectFilters ($ query , $ filter );
27162732 return $ filter ;
27172733 }
@@ -2720,8 +2736,10 @@ protected function buildFilter(Query $query): array
27202736 $ filter [$ attribute ]['$in ' ] = $ value ;
27212737 } elseif ($ operator == '$ne ' && \is_array ($ value )) {
27222738 $ filter [$ attribute ]['$nin ' ] = $ value ;
2739+ } elseif ($ operator == '$all ' ) {
2740+ $ filter [$ attribute ]['$all ' ] = $ query ->getValues ();
27232741 } elseif ($ operator == '$in ' ) {
2724- if ($ query ->getMethod () === Query::TYPE_CONTAINS && !$ query ->onArray ()) {
2742+ if (in_array ( $ query ->getMethod (), [ Query::TYPE_CONTAINS , Query:: TYPE_CONTAINS_ANY ]) && !$ query ->onArray ()) {
27252743 // contains support array values
27262744 if (is_array ($ value )) {
27272745 $ filter ['$or ' ] = array_map (function ($ val ) use ($ attribute ) {
@@ -2798,6 +2816,8 @@ private function handleObjectFilters(Query $query, array &$filter): void
27982816 switch ($ query ->getMethod ()) {
27992817
28002818 case Query::TYPE_CONTAINS :
2819+ case Query::TYPE_CONTAINS_ANY :
2820+ case Query::TYPE_CONTAINS_ALL :
28012821 case Query::TYPE_NOT_CONTAINS : {
28022822 $ arrayValue = \is_array ($ queryValue ) ? $ queryValue : [$ queryValue ];
28032823 $ operator = $ isNot ? '$nin ' : '$in ' ;
@@ -2882,6 +2902,8 @@ protected function getQueryOperator(string $operator): string
28822902 Query::TYPE_GREATER => '$gt ' ,
28832903 Query::TYPE_GREATER_EQUAL => '$gte ' ,
28842904 Query::TYPE_CONTAINS => '$in ' ,
2905+ Query::TYPE_CONTAINS_ANY => '$in ' ,
2906+ Query::TYPE_CONTAINS_ALL => '$all ' ,
28852907 Query::TYPE_NOT_CONTAINS => 'notContains ' ,
28862908 Query::TYPE_SEARCH => '$search ' ,
28872909 Query::TYPE_NOT_SEARCH => '$search ' ,
@@ -3550,12 +3572,11 @@ protected function processException(\Throwable $e): \Throwable
35503572 }
35513573
35523574 // Duplicate key error
3553- if ($ e ->getCode () === 11000 ) {
3554- return new DuplicateException ('Document already exists ' , $ e ->getCode (), $ e );
3555- }
3556-
3557- // Duplicate key error for unique index
3558- if ($ e ->getCode () === 11001 ) {
3575+ if ($ e ->getCode () === 11000 || $ e ->getCode () === 11001 ) {
3576+ $ message = $ e ->getMessage ();
3577+ if (!\str_contains ($ message , '_uid ' )) {
3578+ return new DuplicateException ('Document with the requested unique attributes already exists ' , $ e ->getCode (), $ e );
3579+ }
35593580 return new DuplicateException ('Document already exists ' , $ e ->getCode (), $ e );
35603581 }
35613582
0 commit comments