No, my sense is you understood perfectly. If there were any misunderstanding it’d be on me.
You could use posts_where filter, but it’s not optimal for our needs. This filter is best when altering a query in a way that cannot be addressed by normal WP_Query arguments. Like if you did need to search in the guid field. I remind you to not actually do this, there’s a reason WP_Query does not cover this field ??
Generally speaking, the best hook to alter queries that use WP_Query methods is the “pre_get_posts” action. The default search query goes through this action, so there’s no need to alter your search form if it’s using the default search action. Something like example.com/index.php?s=search terms . Or any other method that uses WP_Query.
The first things your pre_get_posts callback should do is confirm the passed query is the main query and that it’s a search query. If so, set the “meta_query” query var as required to include the attached file field as part of the search query.
There is one rather serious problem in the resulting query I think. When you add a meta_query argument it is added to the other constraints with a logical AND. I’m fairly sure you want a logical OR for this. Do verify this is the case. You can use that posts_where filter to do this. If so, you’ll also need to use the posts_where filter to change that critical AND to an OR.
Part of the problem with using posts_where is it’s difficult for your callback to know when to apply a change and when not to. Because we already worked this out in pre_get_posts, we can add the posts_where filter from within the pre_get_posts callback so we’re sure it’ll only be applied to our search queries.
The other reason posts_where would not work on it’s own is the postmeta table needs to be joined in, which is outside the scope of posts_where. There is a “posts_request” filter where your callback is passed the entire SQL query, but code that alters a query string is inherently fragile when compared to setting query args in pre_get_posts. We should try to keep fragile code to a minimum even if it means using two hooks instead of one.
If there’s any chance for misunderstanding, this will be it. If anything here is not clear, don’t hesitate to ask for clarification.