Использование cfloop с функцией queryfilter

Я новичок в ColdFusion и пытаюсь использовать cfloop для кода ниже:

<cfscript>
    var origRate = 0;
    var toRate = 0;

    rates = myQuery.filter(function (obj) {
          return (obj.code == arguments.origCode || obj.code == 
    arguments.toCode)
            })
</cfscript>

Ниже я изменил исходный код и вставил указанный выше новый код, чтобы избежать встроенных запросов sql:

<cfquery name="rates" dbtype="query">
        select code, rate
  from myQuery
  where code = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.origCode#" />
     or code = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.toCode#" />
</cfquery>

Я попытался использовать cfloop без изменения предыдущего кода, как показано ниже, но он не работает:

<cfloop query="rates">
    <cfscript>
        if (code == arguments.origCode) origRate = rate;
        if (code == arguments.toCode) toRate = rate;
    </cfscript>
</cfloop>

Как только второй блок кода был вставлен путем комментирования первого блока кода выше, он не загружал страницу. Если у кого-то есть идея, я очень ценю это. Заранее спасибо!


person S M    schedule 27.11.2018    source источник
comment
Простое утверждение not working слишком расплывчато. Укажите ожидаемые и фактические результаты для этого кода.   -  person Dan Bracuk    schedule 28.11.2018
comment
Еще пара замечаний. Почему вы переключаетесь с tags на script для цикла? for петли так же просты, как <cfloop>. Например, for (rate in rates) {...} petefreitag.com/cheatsheets/coldfusion/cfscript Ваша условная логика выглядит неправильно. к. Должно быть rate = (code EQ arguments.origCode) ? origRate : "";   -  person fyroc    schedule 28.11.2018
comment
Что именно ты пытаешься сделать? Что происходит между вашей фильтрацией myquery и просмотром этих результатов? Возможно, вам даже не потребуется выполнять два разных прохода по результатам запроса. Можете ли вы предоставить некоторые основные данные и некоторые основные ожидания в отношении того, что вы хотите?   -  person Shawn    schedule 28.11.2018
comment
Я изменил вопрос @Shawn. Надеюсь теперь понятно. До изменения исходного кода он работал.   -  person S M    schedule 28.11.2018
comment
Итак, чего вы пытаетесь достичь? Если вам просто нужно отфильтровать свой запрос, сделайте это в самом запросе. Ваш исходный код хорош. Вы не хотите возвращать результат запроса, чтобы просто отфильтровать его в коде. filter() может сделать с запросом то же самое, что и предложение WHERE, но SQL НАМНОГО лучше выполняет эту фильтрацию. Если вы хотите использовать filter() в запросе, это действительно необходимо только в том случае, если вам нужно также использовать базовый запрос (или другую отфильтрованную версию) где-то еще.   -  person Shawn    schedule 28.11.2018
comment
Но предпочтительнее использовать фильтр, а не sql из-за требований и не может использовать встроенные запросы sql.   -  person S M    schedule 28.11.2018
comment
Почему? Если ваш SQL-запрос не дает вам нужных данных, вам может потребоваться исправить запрос. SQL гораздо более подходящее место для фильтрации результатов.   -  person Shawn    schedule 28.11.2018
comment
Будет ли ваш myQuery возвращать более одной строки для ставок? Вам нужно зациклить его? Если вы это сделаете, вы перезапишете origRate и toRate тем, что окажется последней строкой запроса.   -  person Shawn    schedule 28.11.2018
comment
Глядя на логику, кажется, что вы пытаетесь отправить origCode и toCode в свой запрос, чтобы получить обратно origRate и toRate. Может ли значение code дублироваться в вашей таблице или этот столбец уникален? И могут ли origCode и toCode быть одним и тем же значением, чтобы тянуть один и тот же rate? Кажется, есть много дополнительной обработки, которую можно реорганизовать. Можете ли вы предоставить некоторые примеры данных и что вы ожидаете получить?   -  person Shawn    schedule 29.11.2018
comment
Я понимаю, что вы можете быть ограничены в использовании встроенных запросов. Но, по моему мнению, это должно быть серьезным препятствием, потому что ваши возможности по получению данных будут значительно ограничены, и это также значительно увеличит использование ресурсов, если вам придется передавать большой набор данных, а затем фильтровать их в своем приложении. База данных — это не просто носитель данных. Если вы не можете получить необходимые данные, вам может потребоваться поговорить с вашим администратором баз данных, чтобы получить хранимую процедуру, которую вы можете использовать. Это уберет ваш фактический запрос из вашего канала, но все же позволит вам правильно отфильтровать.   -  person Shawn    schedule 29.11.2018


Ответы (2)


Не хватало некоторых подробностей о приложении и данных, поэтому я сделал пару предположений. Похоже, у вас есть объект запроса, который вы хотите отфильтровать и получить оценки для origCode и toCode. Не зная больше о вашей структуре данных и о том, что вы планируете с ней делать, я могу лишь сделать несколько общих предложений. Я по-прежнему утверждаю, что фильтрация в запросе была бы намного лучше, но я понимаю ограничения. Поскольку вам необходимо фильтровать внутри приложения, как большая часть базовых данных, которые вы изначально возвращаете, так и обработка для фильтрации этих записей будут негативно влиять на производительность.

Первое, что я сделал, это создал поддельный объект запроса. Вот где мое первое предположение вступает в игру. Я предположил, что ваш code не будет дублироваться в вашей таблице и что код будет иметь связанный с ним rate.

myQuery = queryNew(
    "code, rate",
    "integer, integer",
    [
      { "code" : 1 , "rate" : 10 } , 
      { "code" : 2 , "rate" : 15 } , 
      { "code" : 3 , "rate" : 20 } , 
      { "code" : 4 , "rate" : 25 } , 
      { "code" : 5 , "rate" : 30 }
    ]
);

Я бы не рекомендовал здесь Query of Query, потому что это требует больших накладных расходов для чего-то, что может быть выполнено довольно легко.

Я создал функцию, которую вы можете передать в свои origCode и toCode, и она вернет вам структуру origRate и toRate. Я включил некоторые комментарии в код, чтобы вы могли видеть, что я делаю. Основная часть функции использует замыкание filter() для фильтрации записей запроса. Если вы можете фильтровать через SQL, вы сможете устранить этот блок.

function returnNewRates( required Numeric origCode, required Numeric toCode ) {
    local.ratesStruct = { "origRate":-1, "toRate":-1 } ;

    // This will be our query. If we _have_ to use an existing query, pass it in and duplicate() it. (Pass by Reference!)
    local.qry = duplicate( myQuery )  ; 
    /////////////
    // Closure to filter the query. This should be done in SQL.
    // https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-m-r/queryfilter.html
    local.filteredQuery = qry
        .filter( function (obj) {
                return ( obj.code == origCode || obj.code == toCode ) ;
        } ) ;

    // Now assign new rates. NOTE: The query shouldn't return more than 2 rows. We can validate if needed.
    for ( var r IN filteredQuery ) {
        if( r.code == arguments.origCode ) { ratesStruct.origRate = r.rate ; }
        if( r.code == arguments.toCode ) { ratesStruct.toRate = r.rate ; }
    }

    return ratesStruct ;
}

Чтобы назначить origRate и toRate, мы сначала создаем возвращаемое значение ratesStruct, чтобы сохранить структуру ставок. После того, как мы отфильтровали наш запрос, мы просто просматриваем эти отфильтрованные результаты и проверяем, соответствует ли code в строке нашим входным переменным. Еще одно из моих предположений заключалось в том, что база данных будет возвращать не более двух записей (одну origCode и одну toCode или ни одну). Если возможно вернуть более одной строки для code, то выходные коды будут перезаписаны последней связанной строкой в ​​запросе. Если есть другие строки, подходящие для сортировки, то их можно использовать и выбрать только верхнюю строку для нужной ставки. Я также по умолчанию установил для возвращаемых ставок значение -1, чтобы показать, что для code не найдено rate. Это можно изменить при необходимости.

После этого я просто провел несколько тестов, чтобы убедиться, что у нас нет шатаний. Код находится по адресу https://trycf.com/gist/c3b87ca7c508562fd36f3ba6c73829c7/acf2016? .

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

person Shawn    schedule 29.11.2018

Если вы получаете сообщение об ошибке о недопустимой конструкции, это связано с тем, что версия CF не поддерживает оператор ==. Для Adobe ColdFusion до недавнего времени единственными поддерживаемыми операторами равенства были eq, is или различные функции сравнения в зависимости от задействованных переменных и намерений.

<cfloop query="rates">
    <cfscript>
        if (code eq arguments.origCode) origRate = rate;
        if (code eq arguments.toCode) toRate = rate;
    </cfscript>
</cfloop>
person Dan Roberts    schedule 28.11.2018
comment
Работают ли эти условные операторы с CF? Похоже, он пытается составить маршрут, но не совсем там. - person fyroc; 28.11.2018
comment
троичный? нет, это просто базовое условное и заданное. Я полагаю, вы думаете о таком утверждении, как origRate = code eq arguments.origCode ? rate : '' - person Dan Roberts; 28.11.2018
comment
Ага, автокоррекция. Я жил в мире PHP и не знал, что вы можете сделать такой условный набор с CF. Спасибо за подтверждение. - person fyroc; 28.11.2018
comment
@DanRoberts, что условные операторы в порядке. Я думаю, что значение, присвоенное запросу, неверно. Спасибо - person S M; 28.11.2018
comment
@SM - Непонятно, что вы имеете в виду под неправильным. Не могли бы вы обновить свой вопрос, приведя пример фактических результатов и чем они отличаются от того, что вы ожидали? - person SOS; 28.11.2018
comment
@Ageax, я изменил вопрос. Надеюсь теперь понятно. До изменения исходного кода он работал. Это означает, что я не модифицировал этот блок кода cfloop и не беспокоюсь о нем. - person S M; 28.11.2018
comment
Не совсем :) Что ты имеешь в виду под не загрузил страницу? Вы получаете сообщение об ошибке? Неверный вывод? - person SOS; 29.11.2018