Elasticsearch嵌套查询Groovy脚本Date.parse参数不匹配报错求助
missing_method_exception in Elasticsearch Groovy Script for Date Comparison Let's break down what's going wrong here and fix that script step by step—no more unnecessary date string gymnastics!
The Root Cause
Your error No signature of method: static java.util.Date.parse() is applicable for argument types: (java.lang.String, java.lang.Long) happens because you're passing a millisecond timestamp (long) to Date.parse(), but this method expects a human-readable string date. All that extra formatting and re-parsing you're doing isn't just redundant—it's causing the method mismatch.
Elasticsearch stores date fields as millisecond timestamps under the hood, so we can skip all the string conversion and compare timestamps directly. This is way more efficient and avoids the error entirely.
The Corrected Query Script
Here's a cleaned-up, working version of your query that properly implements your requirement: filter documents where at least one rotation group has all project end dates earlier than today.
First, a straightforward loop-based version that's easy to follow:
{ "query": { "bool": { "filter": { "script": { "script": { "lang": "groovy", "inline": """ def now = System.currentTimeMillis(); // Loop through each rotation group in the document for (rotation in doc['rotation_list']){ def allEnded = true; // Check every end date in this rotation group for (endDate in rotation['project_end_date.end_date'].values){ if (endDate >= now){ allEnded = false; break; // No need to check further if one date is not expired } } // If any group has all expired dates, return true if (allEnded){ return true; } } return false; """ } } } } } }
If you prefer more concise code, we can use Groovy's stream API to simplify the logic even further:
{ "query": { "bool": { "filter": { "script": { "script": { "lang": "groovy", "inline": """ def now = System.currentTimeMillis(); // Check if any rotation group has ALL end dates before today doc['rotation_list'].stream() .anyMatch(rotation -> rotation['project_end_date.end_date'].values.stream() .allMatch(endDate -> endDate < now) ) """ } } } } } }
Key Improvements & Explanations
- Removed redundant date conversion: We use
System.currentTimeMillis()to get the current time as a millisecond timestamp, which matches exactly how Elasticsearch stores yourend_datevalues. No more formatting/parsing hoops! - Fixed nested field traversal: The script correctly iterates over each
rotation_listentry first, then checks allproject_end_dateentries within that group—aligning with your nested mapping structure. - Simplified logic: The stream version uses
anyMatchto find at least one valid rotation group, andallMatchto verify every end date in that group is expired. This makes the code shorter and more readable.
Testing with Your Sample Data
Your test data has all end dates in 2020, which are definitely earlier than today. The corrected script will return this document as a match, exactly as you intended.
内容的提问来源于stack exchange,提问作者Abhishek

