如何用Mongoose 4.13.11查询数组元素字段不匹配的文档?
Hey there! Let's work through this query challenge you're dealing with. Since you're on Mongoose 4.13.11, we need a solution that's compatible with that version, and both $expr and $where can work here—let's break down the best approaches.
Option 1: Use $expr (Recommended for Better Performance)
MongoDB 3.6+ (which Mongoose 4.13.x supports) introduced $expr, letting you compare fields within the same document directly in query filters. To check if any element in your array has a last_message_read.messageId that doesn't match the document's last_message, we can combine $expr with $map and $anyElementTrue:
// Replace "YourModel" with your actual model name, and adjust field names as needed YourModel.find({ user_id: "target-user-id", // Add your user_id filter here $expr: { $anyElementTrue: { $map: { input: "$yourArrayField", // Replace with your array field's name as: "arrayItem", in: { $ne: ["$$arrayItem.last_message_read.messageId", "$last_message"] } } } } }) .then(docs => console.log("Matching documents:", docs)) .catch(err => console.error("Query error:", err));
How this works:
$mapiterates over every element in your array, returning a boolean array where each value istrueif the element'slast_message_read.messageIddoesn't equal the document'slast_message.$anyElementTruechecks if there's at least onetruein that boolean array—if yes, the document matches the filter.- We add your
user_idcondition directly in the query object, so it combines seamlessly with the$exprlogic.
Option 2: Use $where (Alternative for Edge Cases)
If for some reason $expr isn't working for you, $where lets you write a JavaScript function to evaluate the condition. Note that this is less performant than $expr (since it runs JS on each document), but it's a valid fallback:
YourModel.find({ user_id: "target-user-id", $where: function() { // Add checks to avoid errors if nested fields are missing if (!this.yourArrayField || !this.last_message) return false; return this.yourArrayField.some(arrayItem => { return arrayItem.last_message_read && arrayItem.last_message_read.messageId !== this.last_message; }); } })
Important notes for $where:
- Always add checks for nested fields (like
arrayItem.last_message_read) to avoid runtime errors if some documents don't have those fields. - Avoid using user input directly in
$wherefunctions—this can lead to security vulnerabilities.
Both approaches let you combine the user_id condition with your array mismatch check. Stick with $expr whenever possible for better query performance and compatibility with MongoDB's query optimizer.
内容的提问来源于stack exchange,提问作者Landon Vago-Hughes

