Можете ли вы отфильтровать строки в Query of Queries, используя значение свойства значения столбца struct? - PullRequest
2 голосов
/ 03 мая 2019

Если в качестве значения столбца строки в объекте запроса CF используется объект, такой как Array или Struct. Можно ли использовать свойства этого объекта в предложении WHERE запроса запросов для ограничения набора результатов?

Дано:

<cfset local.exampleArray=[
    {   id:1,
        nestedArray:["Tom","Dick","Harry"],
        nestedStruct:{nid:42,name:"unknown"}
    },
    {   id:2,
        nestedArray:["John","Paul","Ringo","George"],
        nestedStruct:{nid:12,name:"rockstars"}
    },
    {   id:3,
        nestedArray:["Bonny","Clyde"],
        nestedStruct:{nid:43,name:"criminals"}
    },
]>
<cfset local.exampleQuery=queryNew("id,nestedArray,nestedStruct","integer,object,object",local.exampleArray)>

Запросы запросов:

<cfquery dbtype="query" name="local.exampleQoQ">
    SELECT *
    FROM   [local].exampleQuery
    WHERE  nestedStruct.nid=12
</cfquery>

<cfquery dbtype="query" name="local.exampleQoQ2">
    SELECT *
    FROM   [local].exampleQuery
    WHERE  nestedArray.length=3
</cfquery>

Результаты в запросе ошибки выполнения: nestedStruct.nid / nestedArray.length не соответствует ни одной таблице в списке таблиц FROM

Если в предложении WHERE не используются столбцы типа объекта, объекты возвращаются правильно при запросе и ведут себя как ожидалось:

<cfquery dbtype="query" name="local.exampleQoQ">
    SELECT *
    FROM   [local].exampleQuery
    WHERE  id=1
</cfquery>
<cfoutput query="local.exampleQoQ">
    #local.exampleQoQ.id#:#ArrayLen(local.exampleQoQ.nestedArray)#:#local.exampleQoQ.nestedStruct.nid#
</cfoutput>

В результате "1: 3: 42"

Это просто проблема, когда реализация QoQ не поддерживает доступ к свойствам объекта значения столбца?

1 Ответ

2 голосов
/ 04 мая 2019

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

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

Вы не хотите Query of Query для этого.Это уже очень ограниченный аспект «запроса» CF, и его следует использовать только при необходимости.Если вы используете ColdFusion 2016+, вы можете использовать добавленную функцию: queryFilter().

Используя вышеприведенную настройку в разделе «Given:», вы можете использовать следующее:

<cfscript>
    /* Instead of QoQ, limit your Query with queryFilter() */
    filteredQuery = queryFilter( exampleQuery
        ,function(o){ return o.nestedStruct.NID == 12 ;
        }
    ) ;
</cfscript>

, который даст вам переменную filteredQuery, которая содержит:

filteredQuery

Тогда вы можете просто обратиться к filteredQuery.nestedArray, чтобы получить массив «Джон, Пол, Джордж и Ринго».

Но вы также хотите отфильтроватьмассив в nestedArray должен быть 3 элемента.Таким образом, вы можете просто добавить еще одно условие для возврата обратного вызова:

local.filteredQueryForLength = queryFilter( 
    local.exampleQuery2,
    function(o){ return o.nestedStruct.NID == 12 && arrayLen(o.nestedArray) == 3 ; }
) ;

, что затем даст вам пустой объект запроса, поскольку в filteredQuery.nestedArray, которые вы выбрали, есть 4 элемента.

Наконец, queryFilter имеет функцию-член, которая просто filter(), поэтому вы можете быть еще короче и использовать это:

local.filteredQueryForLength2 = local.exampleQuery3.filter(
    function(o){ return o.nestedStruct.NID == 12 && o.nestedArray.len() == 3 ; }
) ;

Также помните, что объекты запросов ColdFusion являются Pass-По ссылке, поэтому, если вы делаете что-либо (например, filter()), которое модифицирует объект, он изменит этот базовый объект, поэтому он будет другим, если вы снова его используете.Это также означает, что вам не нужно присваивать его переменной.Вы можете просто позвонить queryFilter и затем обратиться к исходному объекту запроса. And another note: when using CF Script syntax (which I much prefer), don't forget that = is assignment and == is comparison. I forgot that initially and all of the records were returning with nestedStruct.NID as 12`.: - /

Последнее примечание: я создал скрипку в https://trycf.com/gist/031a090059a46cd471aa44627fc7ee12/acf2016?theme=monokai. Я добавил еще один элемент в ваш смоделированный запрос, чтобы вы могли видеть, как выглядит ваш возвращаемый объект, с несколькими элементами, соответствующими фильтрам,

...