Есть ли способ поместить $ regexMatch в определенное поле на каждом уровне объекта в конвейере агрегации MongoDB?

#python #mongodb #aggregation-framework #full-text-search #eve

#python #mongodb #aggregation-framework #полнотекстовый поиск #eve

Вопрос:

Есть ли способ настроить конвейер агрегации MongoDB для выполнения a $regexMatch для каждого «текстового» поля независимо от того, на каком уровне оно находится. В настоящее время я использую текстовые индексы с подстановочными знаками для обработки создания текстового индекса: https://docs.mongodb.com/manual/core/index-text/#wildcard-text-indexes

Я хочу, чтобы это $regexMatch было сделано для каждого «текстового» поля. Мы хотим возвращать только те документы, в которых есть пользовательский текстовый запрос внутри поля «текст», и иметь конвейер, масштабируемый до того, чтобы в будущем мы могли выполнять поиск по текстовому запросу практически по всем «текстовым» полям без необходимости возвращаться и что-либо менять, если мы можем этого избежать. Вот что у меня есть для моей текущей схемы («collection_items» — это имя корневого ключа в моей коллекции):

 "collection_items": [{
 "title": "The Title",
 "text": "We Want to do a text search on this field",
 "text_ideas": {
     "one_idea":{
         "idea_title":
         "text": "Some more text we want to look for user text query"
     },
     "second_idea":{
             "idea_title"
             "text": "Even more text we want to look for user text query"
         }
     }
}]
  

Я пытался обработать случай, когда у меня есть поле ‘text’ в объекте внутри объекта (например, текстовое поле, показанное в ‘one_idea’ и ‘second_idea’), но не повезло. Вот что я пробовал:

 {
                "$match": {
                    "$text": {
                        "$search": "$word",
                        "$language": "en",
                        "$caseSensitive": False,
                    }
                }
            },


"$addFields": {
                    "collection_items": {
                        "$filter": {
                            "input": {"$objectToArray": "$$collection_items.item"},
                            "as": "item",
                            "cond": {
                                {
                                    "$filter": {
                                        "input": {"$objectToArray": "$$item.v"},
                                        "as": "secondItem",
                                        "cond": {
                                            {
                                                "$regexMatch": {
                                                    "input": "$$secondItem.v.text",
                                                    "regex": "$word",
                                                    "options": "i",
                                                }
                                            },
                                        }
                                    }
                                }
                            }
                        }
                    },
  

Но я продолжаю получать ошибку:
TypeError: unhashable type: 'dict'

Ответ №1:

Теоретически ваш подход «хорош», если вы устраняете перегибы, вам нужно убедиться, что вы действительно запрашиваете поля, которые вы хотите запросить, и на данный момент это не так.

Однако рассматривали ли вы вместо этого создание подстановочного текстового индекса? это автоматически индексирует каждое текстовое поле в вашем документе. (obv вы также можете просто выбрать, какие поля вы хотите проиндексировать).

После этого вы можете использовать оператор $text для поиска по этому индексу.

Комментарии:

1. Да, в настоящее время я использую текстовый индекс с подстановочными знаками, у меня возникли проблемы с фильтрацией, поскольку мы хотим возвращать только документы, в которых есть пользовательский текстовый запрос внутри поля «текст»