问题
So I have a field called 'city' in my results...the results are corrupted, some times it's an actual name, sometimes it's a number. The following code displays all the records...
db.zips.aggregate([{$project : {city:{$substr:["$city",0,1]}}},{$sort : {city : 1}} ])
I need to modify this line to display only the records with a city who has a name that is a number (2,3,4, etc)....I think I can use '$match', but how?
db.zips.aggregate([{$project : {city:{$substr:["$city",0,1]}}},{$sort : {city : 1}}, {$match:{???what_to_say_here???} ])
How to say 'match when city is a number'?
the out put I get looks like this...
{
"city" : "A",
"_id" : "04465"
},
{
"city" : "1",
"_id" : "02821"
},
{
"city" : "0",
"_id" : "04689"
}
I'm trying to display only the records with a numeric string...this is related to a larger "homework" problem but I can't even get to the actual homework question until I get past this point.
回答1:
Use the $type operator in your $match:
db.zips.aggregate([
{$project : {city:{$substr:["$city",0,1]}}},
{$sort : {city : 1}},
{$match: {city: {$type: 16}}} // city is a 32-bit integer
]);
There isn't a single type value for number so you need to know which type of number you have:
32-bit integer 16
64-bit integer 18
Double 1
Or use an $or operator to match all types of numbers:
db.zips.aggregate([
{$project : {city:{$substr:["$city",0,1]}}},
{$sort : {city : 1}},
{$match: {$or: [{city: {$type: 1}}, {city: {$type: 16}}, {city: {$type: 18}}]}}
]);
Or even use $not to match all docs where city is not a string:
db.zips.aggregate([
{$project : {city:{$substr:["$city",0,1]}}},
{$sort : {city : 1}},
{$match: {city: {$not: {$type: 2}}}} // city is not a string
]);
UPDATED
To match all docs where city is a numeric string you can use a regular expression:
db.zips.aggregate([
{$project : {city:{$substr:["$city",0,1]}}},
{$sort : {city : 1}},
{$match: {city: /^\d.*$/}} // city is all digits
]);
回答2:
Why not to use $regex?
db.zips.aggregate([
{$project : {city:{$substr:["$city",0,1]}}},
{$sort : {city : 1}},
{$match: {city:{$regex:'[0-9]'}}}
])
回答3:
Simply use:
db.zips.aggregate([
{$match: {
'city': { $regex: '^[0-9].*'}
}}])
This work fine for me!
回答4:
An easier way to match all docs where city is a numeric string is using the property '0' <= city <= '9' i.e. your aggregation query becomes:
db.zips.aggregate([
{$project : {city:{$substr:["$city",0,1]}}},
{$sort : {city : 1}},
{$match: {city: {$gte: '0', $lte: '9'}}}
]);
When using JohnnyHK's suggestion of a regex you can save yourself the $project stage altogether.
回答5:
You can also use an in command
db.zips.aggregate([
{
$project: {
first_char: {
$substr : ["$city",0,1]
},
"_id":"$_id"
}
},
{
$match: {
first_char: {
$in: ["0","1","2","3","4","5","6","7","8","9"]
}
}
}
])
回答6:
you can also try like the following, using regular expression without using $regex
db.zips.aggregate([
{$project : { city : { $substr : ["$city",0,1] } }},
{$sort : {city : 1}},
{$match: { city:/[0-9]/}}
])
回答7:
db.zips.aggregate([
{$project : {city:{$substr:["$city",0,1]},pop:1}},
{$group:{_id:"$city",sumPop:{$sum:"$pop"}}},
{$sort : {_id : 1}},
{$match:{_id : {$regex:/\d/}} },
{$group:{_id:"id",sumPop:{$sum:"$sumPop"}}},
]);
回答8:
With the mongodb 4.4 (upcoming), You can use $isNumber pipeline operator to check whether the expression is integer or other BSON type.
db.zips.find({ "$expr": { "$anyElementTrue": { "$isNumber": "$city" }}})
$isNumber will return true or false corrsoponding to the expression and $anyElementTrue will return the $matched documents.
来源:https://stackoverflow.com/questions/13409386/how-to-say-match-when-field-is-a-number-in-mongodb