如何在MongoDB中同时查询两个数组?
How to query on two arrays at the same time in MongoDB?
我有以下文档,其中每个文档都有字段 values
和 dates
,它们是数组。这些数组在每个文档中始终具有相同的大小,这意味着 dates
中的每个值对应于 values
:
中的一个值
[
{
_id: "Stock1",
values: [
1,
2,
3
],
dates: [
ISODate("2000-01-01"),
ISODate("2010-01-01"),
ISODate("2020-01-01")
]
},
{
_id: "Stock2",
values: [
4,
5,
],
dates: [
ISODate("2000-01-01"),
ISODate("2010-01-01")
]
},
{
_id: "Stock3",
values: [
7,
8,
9
],
dates: [
ISODate("2000-01-01"),
ISODate("2010-01-01"),
ISODate("2020-01-01")
]
}
]
我想查询我的文档,以便在 dates
“2010-01-01”和 dates
“2020-01-01”(包括)之间获得 values
仅适用于“Stock1”和“Stock3”,即我想以:
[
{
_id: "Stock1",
values: [
2,
3
],
dates: [
ISODate("2010-01-01"),
ISODate("2020-01-01")
]
},
{
_id: "Stock3",
values: [
8,
9
],
dates: [
ISODate("2010-01-01"),
ISODate("2020-01-01")
]
}
]
目前,我正在做以下事情:
db.collection.aggregate([
{
$match: {
_id: {
$in: [
"Stock1",
"Stock3"
]
}
}
},
{
$unwind: {
path: "$dates",
includeArrayIndex: "date_index"
}
},
{
$match: {
dates: {
$gte: ISODate("2010-01-01"),
$lte: ISODate("2020-01-01")
}
}
},
{
$unwind: {
path: "$values",
includeArrayIndex: "value_index"
}
},
{
$match: {
$expr: {
$eq: [
"$date_index",
"$value_index"
]
}
}
},
{
$project: {
date_index: 0,
value_index: 0
}
}
])
但我还没到那一步。此外,管道看起来很长且次优。有更好的方法吗?最后,我首先在 dates
上使用 unwind
,然后在 values
上再次使用 unwind
之前进行过滤:这是为了避免管道中的许多文档太大,因为数组 dates
和 values
可能很大。
如有任何帮助,我们将不胜感激!
查询
- 匹配只保留
"Stock1","Stock3"
- 筛选日期
(range (size "$dates"))
的索引,以仅获取日期在 [2010-2020]
范围内的元素的索引
- 2 映射以从
dates
和 values
中获取那些过滤后的索引
*我们可以像 1 个 reduce 一样完成所有操作,但它会嵌套且代码更复杂,而且 $concatArrays
很慢,将数组减少到 array.The 不是一个好主意,下面更简单和甚至可以用于非常大的数组。
aggregate(
[{"$match": {"_id": { "$in": ["Stock1","Stock3"]}}}
{"$set":
{"indexes":
{"$filter":
{"input": {"$range": [0, {"$size": "$dates"}]},
"cond":
{"$and":
[{"$gte":
[{"$arrayElemAt": ["$dates", "$$this"]},
ISODate("2010-01-01T00:00:00Z")]},
{"$lte":
[{"$arrayElemAt": ["$dates", "$$this"]},
ISODate("2020-01-01T00:00:00Z")]}]}}}}},
{"$set":
{"dates":
{"$map":
{"input": "$indexes",
"in": {"$arrayElemAt": ["$dates", "$$this"]}}}}},
{"$set":
{"values":
{"$map":
{"input": "$indexes",
"in": {"$arrayElemAt": ["$values", "$$this"]}}}}},
{"$unset": ["indexes"]}])
我有以下文档,其中每个文档都有字段 values
和 dates
,它们是数组。这些数组在每个文档中始终具有相同的大小,这意味着 dates
中的每个值对应于 values
:
[
{
_id: "Stock1",
values: [
1,
2,
3
],
dates: [
ISODate("2000-01-01"),
ISODate("2010-01-01"),
ISODate("2020-01-01")
]
},
{
_id: "Stock2",
values: [
4,
5,
],
dates: [
ISODate("2000-01-01"),
ISODate("2010-01-01")
]
},
{
_id: "Stock3",
values: [
7,
8,
9
],
dates: [
ISODate("2000-01-01"),
ISODate("2010-01-01"),
ISODate("2020-01-01")
]
}
]
我想查询我的文档,以便在 dates
“2010-01-01”和 dates
“2020-01-01”(包括)之间获得 values
仅适用于“Stock1”和“Stock3”,即我想以:
[
{
_id: "Stock1",
values: [
2,
3
],
dates: [
ISODate("2010-01-01"),
ISODate("2020-01-01")
]
},
{
_id: "Stock3",
values: [
8,
9
],
dates: [
ISODate("2010-01-01"),
ISODate("2020-01-01")
]
}
]
目前,我正在做以下事情:
db.collection.aggregate([
{
$match: {
_id: {
$in: [
"Stock1",
"Stock3"
]
}
}
},
{
$unwind: {
path: "$dates",
includeArrayIndex: "date_index"
}
},
{
$match: {
dates: {
$gte: ISODate("2010-01-01"),
$lte: ISODate("2020-01-01")
}
}
},
{
$unwind: {
path: "$values",
includeArrayIndex: "value_index"
}
},
{
$match: {
$expr: {
$eq: [
"$date_index",
"$value_index"
]
}
}
},
{
$project: {
date_index: 0,
value_index: 0
}
}
])
但我还没到那一步。此外,管道看起来很长且次优。有更好的方法吗?最后,我首先在 dates
上使用 unwind
,然后在 values
上再次使用 unwind
之前进行过滤:这是为了避免管道中的许多文档太大,因为数组 dates
和 values
可能很大。
如有任何帮助,我们将不胜感激!
查询
- 匹配只保留
"Stock1","Stock3"
- 筛选日期
(range (size "$dates"))
的索引,以仅获取日期在[2010-2020]
范围内的元素的索引
- 2 映射以从
dates
和values
中获取那些过滤后的索引
*我们可以像 1 个 reduce 一样完成所有操作,但它会嵌套且代码更复杂,而且 $concatArrays
很慢,将数组减少到 array.The 不是一个好主意,下面更简单和甚至可以用于非常大的数组。
aggregate(
[{"$match": {"_id": { "$in": ["Stock1","Stock3"]}}}
{"$set":
{"indexes":
{"$filter":
{"input": {"$range": [0, {"$size": "$dates"}]},
"cond":
{"$and":
[{"$gte":
[{"$arrayElemAt": ["$dates", "$$this"]},
ISODate("2010-01-01T00:00:00Z")]},
{"$lte":
[{"$arrayElemAt": ["$dates", "$$this"]},
ISODate("2020-01-01T00:00:00Z")]}]}}}}},
{"$set":
{"dates":
{"$map":
{"input": "$indexes",
"in": {"$arrayElemAt": ["$dates", "$$this"]}}}}},
{"$set":
{"values":
{"$map":
{"input": "$indexes",
"in": {"$arrayElemAt": ["$values", "$$this"]}}}}},
{"$unset": ["indexes"]}])