Mal*_*och 3 javascript mongodb pymongo mongodb-query
我不太擅长谷歌搜索这个答案。
每个记录中可能有大约 115 个不同的字段。集合是 mapreduce 在惊人的大数据集上的输出。
看起来像这样:
{_id:'number1', value:{'a':1, 'b':2, 'f':5}},
{_id:'number2', value:{'e':2, 'f':114, 'h':12}},
{_id:'number3', value:{'i':2, 'j':22, 'z':12, 'za':111, 'zb':114}}
Run Code Online (Sandbox Code Playgroud)
关于如何找到填充了 5 个字段的记录的任何想法?
它仍然不是一个很好的查询,但是有一种更现代的方法可以通过$objectToArray和$redact
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$eq": [
{ "$size": { "$objectToArray": "$value" } },
3
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Run Code Online (Sandbox Code Playgroud)
Where$objectToArray基本上将对象强制转换为数组形式,很像JavaScript 中的Object.keys()和组合.map()。
这仍然不是一个好主意,因为它确实需要扫描整个集合,但至少聚合框架操作使用“本机代码”而不是 JavaScript 解释,就像使用$where.
因此,通常仍建议更改数据结构并尽可能使用自然数组以及存储的“大小”属性,以便进行最有效的查询操作。
是的,可以这样做,但不是以最好的方式。这样做的原因是您实际上是在使用$where运算符查询,该查询使用 JavaScript 评估来匹配内容。不是最有效的方法,因为这永远不能使用索引并且需要测试所有文档:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$eq": [
{ "$size": { "$objectToArray": "$value" } },
3
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Run Code Online (Sandbox Code Playgroud)
这将查找与“三个”元素匹配的条件,然后只会返回您列出的两个文档:
db.collection.find({ "$where": "return Object.keys(this.value).length == 3" })
Run Code Online (Sandbox Code Playgroud)
或者对于“五个”或更多字段,您可以执行相同的操作:
{ "_id" : "number1", "value" : { "a" : 1, "b" : 2, "f" : 5 } }
{ "_id" : "number2", "value" : { "e" : 2, "f" : 114, "h" : 12 } }
Run Code Online (Sandbox Code Playgroud)
因此,该运算符的参数实际上是 JavaScript 语句,在服务器上对其进行评估以返回 where true。
更有效的方法是将元素的“计数”存储在文档本身中。通过这种方式,您可以“索引”此字段,并且查询效率更高,因为不需要扫描其他条件选择的集合中的每个文档来确定长度:
db.numbers.find({ "$where": "return Object.keys(this.value).length >= 5" })
Run Code Online (Sandbox Code Playgroud)
然后要获取具有“五个”元素的文档,您只需要简单的查询:
{_id:'number1', value:{'a':1, 'b':2, 'f':5} count: 3},
{_id:'number2', value:{'e':2, 'f':114, 'h':12}, count: 3},
{_id:'number3', value:{'i':2, 'j':22, 'z':12, 'za':111, 'zb':114}, count: 5}
Run Code Online (Sandbox Code Playgroud)
这通常是最优化的形式。但另一点是,您可能会从一般实践中满意的一般“对象”结构并不是 MongoDB 通常“玩得很好”的东西。问题是对象中元素的“遍历”,这样当您使用“数组”时,MongoDB 会更快乐。即使是这种形式:
db.collection.find({ "count": 5 })
Run Code Online (Sandbox Code Playgroud)
因此,如果您实际上切换到这样的“数组”格式,那么您可以使用一个版本的运算符来计算数组的确切长度$size:
{
'_id': 'number1',
'values':[
{ 'key': 'a', 'value': 1 },
{ 'key': 'b', 'value': 2 },
{ 'key': 'f', 'value': 5 }
],
},
{
'_id': 'number2',
'values':[
{ 'key': 'e', 'value': 2 },
{ 'key': 'f', 'value': 114 },
{ 'key': 'h', 'value': 12 }
],
},
{
'_id':'number3',
'values': [
{ 'key': 'i', 'values': 2 },
{ 'key': 'j', 'values': 22 },
{ 'key': 'z'' 'values': :12 },
{ 'key': 'za', 'values': 111 },
{ 'key': 'zb', 'values': 114 }
]
}
Run Code Online (Sandbox Code Playgroud)
该运算符可以用于数组长度的精确值,因为这是使用该运算符可以完成的操作的基本规定。你不能做的事情记录在“不平等”匹配中。为此,您需要 MongoDB 的“聚合框架”,它是 JavaScript 和 mapReduce 操作的更好替代方案:
db.collection.find({ "values": { "$size": 5 } })
Run Code Online (Sandbox Code Playgroud)
所以这些是替代品。有一种“本机”方法可用于聚合和数组类型。但是相当有争议的是,JavaScript 评估也是 MongoDB 的“原生”,只是因此没有在原生代码中实现。