skip to content
Alvin Lucillo

Conditional projection with switch

/ 2 min read

Yesterday’s entry shows nested conditions, which is hard to read. The updated aggregation pipeline below uses $switch that takes in branches (or the case statements in programming) and the default value (or fallback value).

// test data
// persons data with Philippine landline format:
// (area code) network + local number, e.g. (02) 8123-4567
db.getCollection("persons").insertMany([
	{ name: "Person1", contact_number: "(02) 8123-4567" },
	{ name: "Person2", contact_number: "(02) 8234-5678" },
	{ name: "Person3", contact_number: "(032) 7345-6789" },
	{ name: "Person4", contact_number: "(032) 7456-7890" },
	{ name: "Person5", contact_number: "(082) 8567-8901" },
	{ name: "Person6", contact_number: "(082) 8678-9012" },
	{ name: "Person7", contact_number: "(082) 5567-8901" },
	{ name: "Person8", contact_number: "(082) 5678-9012" },
]);

// Count people per network group:
// 8 -> pldt, 7 -> globe, else -> others
db.getCollection("persons").aggregate([
	{
		$project: {
			match: { $regexFind: { input: "$contact_number", regex: /^\(\d+\)\s*(\d)/ } },
		},
	},
	{
		$project: {
			network_digit: { $arrayElemAt: ["$match.captures", 0] },
		},
	},
	{
		$project: {
			network: {
				$switch: {
					branches: [
						{ case: { $eq: ["$network_digit", "8"] }, then: "pldt" },
						{ case: { $eq: ["$network_digit", "7"] }, then: "globe" },
					],
					default: "others",
				},
			},
		},
	},
	{
		$group: {
			_id: "$network",
			people_count: { $sum: 1 },
		},
	},
	{ $sort: { _id: 1 } },
]);

Output:

[
	{
		"_id": "globe",
		"people_count": 2
	},
	{
		"_id": "others",
		"people_count": 2
	},
	{
		"_id": "pldt",
		"people_count": 4
	}
]