您可以使用结构列值的 属性 值过滤查询查询中的行吗?
Can you filter rows in a Query of Queries using a property value of a struct column value?
如果一个对象,例如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 table list
中的任何 table 不匹配
当不在 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 实现不支持访问列值对象的属性的问题吗?
正如我之前提到的,数据库查询 可以 有一个包含 array/structure-ish 数据的列,但这并不是数据库的真正用途。如您所见,它使查询所需数据变得比应有的困难,并且实际上将数据库视为存储数据的地方。
无论如何,您似乎想通过包含在一列的结构数据中的特定值来过滤查询记录,并且如果另一列数组数据包含一定数量的记录,则还要过滤这些结果。
您不想对此进行查询。它已经是 CF 的一个非常有限的 "query" 方面,应该只在必要时使用。如果您使用的是 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.nestedArray
来得到你的数组 "John, Paul, George and Ringo".
但您还想将 nestedArray
中的数组过滤为 3 个元素。所以你可以在回调中添加另一个条件 return:
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.NIDas
12`。 :-/
最后一点:我在 https://trycf.com/gist/031a090059a46cd471aa44627fc7ee12/acf2016?theme=monokai 创建了一个 Fiddle。我向你的模拟查询添加了一个额外的元素,这样你就可以看到你的 return 对象看起来像多个元素匹配过滤器。
如果一个对象,例如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 table list
中的任何 table 不匹配当不在 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 实现不支持访问列值对象的属性的问题吗?
正如我之前提到的,数据库查询 可以 有一个包含 array/structure-ish 数据的列,但这并不是数据库的真正用途。如您所见,它使查询所需数据变得比应有的困难,并且实际上将数据库视为存储数据的地方。
无论如何,您似乎想通过包含在一列的结构数据中的特定值来过滤查询记录,并且如果另一列数组数据包含一定数量的记录,则还要过滤这些结果。
您不想对此进行查询。它已经是 CF 的一个非常有限的 "query" 方面,应该只在必要时使用。如果您使用的是 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.nestedArray
来得到你的数组 "John, Paul, George and Ringo".
但您还想将 nestedArray
中的数组过滤为 3 个元素。所以你可以在回调中添加另一个条件 return:
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.NIDas
12`。 :-/
最后一点:我在 https://trycf.com/gist/031a090059a46cd471aa44627fc7ee12/acf2016?theme=monokai 创建了一个 Fiddle。我向你的模拟查询添加了一个额外的元素,这样你就可以看到你的 return 对象看起来像多个元素匹配过滤器。