Фильтрация свойств навигации для набора значений с помощью toLowerCase

У меня есть этот запрос JayData (его можно проверить на площадке JSLQ):

northwind.Products
  .filter( function( product ) {
    return  product.ProductName.toLowerCase() in ['tofu'];
  } )
  .toArray( function( products ) {
    console.dir( products );
  } );

По неизвестным причинам этот запрос создает неверное выражение фильтра: http://services.odata.org/Northwind/Northwind.svc/Products?$filter=(tolowerProductName %20eq%20%27tofu%27)&$callback=parent.handleJSONP_21&$format=json

Я выделил неверный параметр жирным шрифтом выше.

Итак, вы видите, что у нас есть tolowerProductName, но оно должно быть tolower(ProductName), поэтому правильный фильтрующий запрос должен выглядеть так: http://services.odata.org/Northwind/Northwind.svc/Products?%24filter=%28tolower%28ProductName%29%20eq%20%27tofu%27%29&%24callback=parent.handleJSONP_21&%24format=json

Кто-нибудь знает обходной путь?

Обновление: проблема возникает только тогда, когда я использую toLowerCase с «в [массиве]», поэтому, например, этот запрос работает нормально:

northwind.Products
  .filter( function( product ) {
    return  product.ProductName in ['Tofu'];
  } )
  .toArray( function( products ) {
    console.dir( products );
  } );

Этот запрос с toLowerCase тоже работает нормально:

northwind.Products
  .filter( function( product ) {
    return  product.ProductName.toLowerCase() == 'Tofu';
  } )
  .toArray( function( products ) {
    console.dir( products );
  } );

Спасибо!


person Sergey    schedule 30.03.2014    source источник


Ответы (2)


Вы пытались установить это выражение в переменную, а затем проверить это в ['tofu']?

person Ken Wheeler    schedule 30.03.2014
comment
он отлично работает без toLowerCase, например. Northwind.Products .filter( function( product ) { return product.ProductName in ['Tofu']; } ) .toArray( function( products ) { console.dir( products ); } ); - person Sergey; 31.03.2014
comment
Является ли product.ProductName строкой? Вы пытались обернуть product.ProductName.toLowerCase() в скобки? - person Ken Wheeler; 31.03.2014
comment
Можете ли вы показать мне пример того, как установить выражение в переменную? Спасибо! - person Sergey; 31.03.2014
comment
var productName = product.ProductName.toLowerCase(); - person Ken Wheeler; 31.03.2014
comment
Затем верните productName в ['tofu'] - person Ken Wheeler; 31.03.2014
comment
Но разве это то, что вы пытаетесь сделать? Разве вы не должны проверять наличие тофу в названии продукта? - person Ken Wheeler; 31.03.2014
comment
хм.. похоже, я не могу сделать это в выражениях фильтра - person Sergey; 31.03.2014
comment
вернуть product.ProductName.toLowerCase().indexOf('тофу') ? - person Ken Wheeler; 31.03.2014
comment
Я использовал этот запрос только для примера. У меня есть эта проблема в реальном проекте со сложным запросом odata. indexOf у меня не работает, и похоже, что odata не поддерживает indexof. поэтому JayData создает этот URL-адрес, и он не работает - services.odata.org/Northwind/Northwind.svc/ - person Sergey; 31.03.2014
comment
о.. Я вижу, что indexof работает нормально: return product.ProductName.toLowerCase().indexOf('tofu') › 0 - person Sergey; 31.03.2014
comment
позвольте мне проверить, могу ли я заменить в ['tofu'] на indexOf('tofu') › 0 в моем реальном проекте - person Sergey; 31.03.2014
comment
В некоторых случаях indexOf может быть обходным путем, но в моем случае у меня есть категория, например. Lorem и поисковый запрос, который может выглядеть так: Lorem 2007, поэтому Lorem.indexOf(Lorem 2007) › 0 всегда ложно. - person Sergey; 31.03.2014
comment
поэтому, чтобы заставить его работать должным образом, мне нужно разделить его пробелом, а затем использовать Lorem.toLowerCase() в ['lorem', '2007'] - person Sergey; 31.03.2014

Я обнаружил, что неправильное выражение фильтра создает эту строку кода (для запроса с оператором «in»):

context.data = temp + context.data.replace(/\(/g, '').replace(/\)/g, '');

Строка 1542 в oDataProvider.js

Я заменил его этим кодом:

context.data = temp + context.data;

И теперь все работает так, как ожидалось. Возможно, я добавил другие проблемы с этим исправлением, но, по крайней мере, оно работает так, как ожидалось, для моих запросов.

Итак, теперь функция VisitSimpleBinaryExpression выглядит так:

VisitSimpleBinaryExpression: function (expression, context) {
        context.data += "(";
        //TODO refactor!!!
        if (expression.nodeType == "in") {
            Guard.requireType("expression.right", expression.type, $data.Expressions.ConstantExpression);
            var paramValue = expression.right.value;
            if (!paramValue instanceof Array) { Guard.raise(new Exception("Right to the 'in' operator must be an array value")); }
            var result = null;
            var orResolution = { mapTo: "or", dataType: "boolean", name: "or" };
            var eqResolution = { mapTo: "eq", dataType: "boolean", name: "equal" };

            paramValue.forEach(function (item) {
                var idValue = item;
                var idCheck = Container.createSimpleBinaryExpression(expression.left, idValue,
                    $data.Expressions.ExpressionType.Equal, "==", "boolean", eqResolution);
                if (result) {
                    result = Container.createSimpleBinaryExpression(result, idCheck,
                    $data.Expressions.ExpressionType.Or, "||", "boolean", orResolution);
                } else {
                    result = idCheck;
                };
            });
            var temp = context.data;
            context.data = '';
            this.Visit(result, context);
            //context.data = temp + context.data.replace(/\(/g, '').replace(/\)/g, '');
            context.data = temp + context.data;
        } else {
            this.Visit(expression.left, context);
            context.data += " ";
            context.data += expression.resolution.mapTo;
            context.data += " ";
            this.Visit(expression.right, context);
        };
        context.data += ")";

    },
person Sergey    schedule 30.03.2014