如果将诸如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实现不支持访问列值对象的属性的问题吗?
答案 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.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创建了一个小提琴。我在模拟查询中添加了一个额外的元素,以便您可以看到带有多个与过滤器匹配的元素的返回对象的外观。