MongoDB使用$elemMatch匹配数组多元素查询失败问题咨询
Absolutely, MongoDB does support this kind of query using $elemMatch—your approach is actually on the right track. Let's break down why you might not be seeing expected results, confirm the correct execution, and cover some edge cases.
First: Your Query Logic Is Correct
Running your exact query against the sample dataset you provided does return the document, because the arrivals array contains an element that matches both conditions:
number: "KL 1451"movement.scheduledTimeLocalincludes"2020-05-23"
Here's how to verify this step-by-step:
1. Insert the Sample Data
First, add your test document to a collection (replace flights with your actual collection name):
db.flights.insertOne({ "departures": [ { "movement": { "airport": { "icao": "EHAM", "iata": "AMS", "name": "Amsterdam" }, "scheduledTimeLocal": "2020-05-23 12:25+01:00", "scheduledTimeUtc": "2020-05-23 11:25Z", "quality": [ "Basic" ] }, "number": "KL 1446", "status": "CanceledUncertain", "codeshareStatus": "IsOperator", "isCargo": false, "aircraft": { "model": "Embraer 190" }, "airline": { "name": "KLM" } }, { "movement": { "airport": { "icao": "EGLL", "iata": "LHR", "name": "London" }, "scheduledTimeLocal": "2020-05-23 14:50+01:00", "scheduledTimeUtc": "2020-05-23 13:50Z", "quality": [ "Basic" ] }, "number": "BA 1309", "status": "Unknown", "codeshareStatus": "IsOperator", "isCargo": false, "aircraft": { "model": "Airbus A319" }, "airline": { "name": "British Airways" } } ], "arrivals": [ { "movement": { "airport": { "icao": "LFPG", "iata": "CDG", "name": "Paris" }, "scheduledTimeLocal": "2020-05-23 21:10+01:00", "scheduledTimeUtc": "2020-05-23 20:10Z", "quality": [ "Basic" ] }, "number": "AF 1472", "status": "Unknown", "codeshareStatus": "Unknown", "isCargo": false, "aircraft": { "model": "Embraer 170" }, "airline": { "name": "Air France" } }, { "movement": { "airport": { "icao": "EHAM", "iata": "AMS", "name": "Amsterdam" }, "scheduledTimeLocal": "2020-05-23 22:15+01:00", "scheduledTimeUtc": "2020-05-23 21:15Z", "quality": [ "Basic" ] }, "number": "KL 1451", "status": "CanceledUncertain", "codeshareStatus": "IsOperator", "isCargo": false, "aircraft": { "model": "Boeing 737-700" }, "airline": { "name": "KLM" } } ] })
2. Run Your Query
Execute your original query (again, replace flights with your collection name):
db.flights.find({ arrivals: { $elemMatch: { 'number': 'KL 1451', 'movement.scheduledTimeLocal': { $regex: /2020-05-23/ } } } })
This will return the full document as expected, since the arrivals array has a matching element.
Why You Might Not Be Seeing Results
If you're getting no hits, check these common issues:
- Wrong collection name: You wrote
db.collection.find(...)—make surecollectionis replaced with your actual collection's name (likeflights,airport_data, etc.). - Hidden whitespace in data: Double-check if the
numberfield in your real data has extra spaces (e.g.,"KL 1451"instead of"KL 1451"). Test with a regex for the number:'number': { $regex: /^KL\s1451$/ } - Regex edge cases: While your regex works for the sample data, if your real timestamps use different formatting, you might need to adjust it (e.g.,
$regex: "2020-05-23", $options: "i"for case insensitivity, though that's not needed here). - Outdated MongoDB version:
$elemMatchhas been supported since MongoDB 2.2, so this is only an issue if you're using a very old version.
Bonus: Return Only Matching Array Elements
If you don't want the entire document and just need the matching arrivals element(s):
- To return the first matching element (all MongoDB versions):
db.flights.find( { arrivals: { $elemMatch: { 'number': 'KL 1451', 'movement.scheduledTimeLocal': { $regex: /2020-05-23/ } } } }, { 'arrivals.$': 1 } // Projects only the first matching array element ) - To return all matching elements (MongoDB 3.2+):
db.flights.aggregate([ { $match: { arrivals: { $elemMatch: { 'number': 'KL 1451', 'movement.scheduledTimeLocal': { $regex: /2020-05-23/ } } } } }, { $project: { arrivals: { $filter: { input: "$arrivals", cond: { $and: [ { $eq: ["$$this.number", "KL 1451"] }, { $regexMatch: { input: "$$this.movement.scheduledTimeLocal", regex: /2020-05-23/ } } ] } } } } } ])
内容的提问来源于stack exchange,提问作者Scotty

