2

如果一个对象(例如 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 实现不支持访问列值对象的属性的问题吗?

4

1 回答 1

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即可获得“约翰、保罗、乔治和林戈”的数组。

但是您还希望将数组过滤为nestedArray3 个元素。因此,您可以在回调返回中添加另一个条件:

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 withnestedStruct.NID as12`。:-/

最后一点:我在https://trycf.com/gist/031a090059a46cd471aa44627fc7ee12/acf2016?theme=monokai创建了一个小提琴。我在您的模拟查询中添加了一个额外的元素,这样您就可以看到您的返回对象与多个匹配过滤器的元素的样子。

于 2019-05-03T23:46:12.813 回答