您是否可以使用struct列值的属性值过滤查询中的行?

时间:2019-05-03 19:57:16

标签: coldfusion qoq

如果将诸如Array或Struct之类的对象用作CF查询对象中行的列值。可以在查询的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 个答案:

答案 0 :(得分:2)

正如我之前提到的,数据库查询可以包含一列包含数组/结构化数据的列,但这并不是数据库的真正用途。如您所见,它使查询所需的数据变得比原本困难的多,并且实际上将数据库当作存储数据的地方而已。

无论如何,您似乎想通过包含在一个列的结构数据内的特定值来过滤查询记录,并且如果另一个列的数组数据包含一定数量的记录,则还要过滤那些结果。

您不希望为此查询。它已经是CF的高度受限的“查询”方面,应仅在必要时使用。如果使用的是ColdFusion 2016+,则可以使用添加的功能:queryFilter()

使用上面“设置:”下的设置,您可以使用以下内容:

<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查询对象是传递参考,因此,如果您做任何修改该对象的操作(例如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创建了一个小提琴。我在模拟查询中添加了一个额外的元素,以便您可以看到带有多个与过滤器匹配的元素的返回对象的外观。