这是单个文档:
function toNumber(str) {
str = String(str).trim();
return !str ? NaN : Number(str);
}
console.log(!isNaN(toNumber("10000"))); // true
console.log(!isNaN(toNumber("100T0"))); // false
console.log(!isNaN(toNumber(""))); // false
我试图仅选择John's BMW的“ carColor”。 像这样:
{
_id: "...",
firstName: "john",
lastName:"Doe",
cars: [
{
"_id": "...",
"carName": "BMW",
"carModel": "330",
"carColor": "silver"
},
{
"_id": "...",
"carName": "Lexus",
"carModel": "IS300",
"carColor": "white"
},
{
"_id": "...",
"carName": "LADA",
"carModel": "2106",
"carColor": "blue"
}
]
}
但是此查询返回完整的对象,如下所示:
db.persons.findOne(
{ "firstName": "John", "cars.carName": "BMW" },
{ "_id": 0, "cars.$.carColor": 1 }
);
我已经尝试了没有。$的其他查询。符号:
{
cars: [
{
"_id": "...",
"carName": "BMW",
"carModel": "330",
"carColor": "silver"
}
}
此版本仅返回“ carColor”属性,但不过滤“ carName”。 像这样:
db.persons.findOne(
{ "firstName": "John", "cars.carName": "BMW" },
{ "_id": 0, "cars.carColor": 1 }
);
有什么想法吗?
答案 0 :(得分:2)
为什么不起作用?
{“ firstName”:“ John”,“ cars.carName”:“ BMW”}
表示“名称为john,并且在汽车数组中至少有一个条目,其中carName为” BMW”的地方”。但是它返回完整的文档,而不过滤数组。
{“ _id”:0,“ cars.carColor”:1}
不投影_id,而是投影car数组所有条目的carColor。
解决方案
实际上,使用查找和投影方法无法完全实现所需的功能。最好做的是像这样添加$ projection operator:
db.collection.find({
firstName: "john",
"cars.carName": "BMW"
},
{
_id: 0,
"cars.$": 1
})
**RESULT**
[
{
"cars": [
{
"_id": "...",
"carColor": "silver",
"carModel": "330",
"carName": "BMW"
}
]
}
]
但是这种方法有缺点:
更好的解决方案
幸运的是,MongoDB通过聚合框架和$filter运算符提供了另一种实现此目标的方法:
db.collection.aggregate([
{
$match: {
firstName: "john"
}
},
{
$project: {
cars: {
$filter: {
input: "$cars",
as: "cars",
cond: {
$eq: [
"$$cars.carName",
"BMW"
]
}
}
}
}
},
{
$project: {
_id: 0,
"colors": "$cars.carColor"
}
}
])
编辑:其他解决方案
您也可以通过展开/分组阶段来尝试:
db.collection.aggregate([
{
$match: {
firstName: "john"
}
},
{
$unwind: "$cars"
},
{
$match: {
"cars.carName": "BMW"
}
},
{
$group: {
"_id": null,
colors: {
$push: "$cars.carColor"
}
}
}
])
答案 1 :(得分:0)
db.persons.find({
firstName: 'john',
cars: {
$elemMatch: {
carName: 'BMW'
}
}
},
{
'cars.$': 1
})
答案 2 :(得分:0)
如果您知道数组中的“ BMW”值不超过一个,那么这是一种通过单个$project
阶段获得结果的方法:
db.getCollection('collection').aggregate([{
$match: {
"firstName": "john"
/* for performance reasons, you may want to include the following line which, however, is not required */
/* this makes sense if you have lots of "john"s with different sets of cars in your database */
, "cars.carName": "BMW" // this will use an index on "cars.carName" if available
}
}, {
$project: {
_id: 0, // do not return the _id field
color: {
$reduce: { // transform the filtered input array
"input": {
$filter: { // remove all non-"BMW" cars from the "cars" array
input: "$cars",
as: "car",
cond: { $eq: [ "$$car.carName", "BMW" ] }
}
},
"initialValue": null,
"in": "$$this.carColor" // just return the color value, nothing else
}
}
}
}])