#mongodb #search #full-text-search #mongodb-atlas #mongodb-atlas-search
#mongodb #Поиск #полнотекстовый поиск #mongodb-atlas #mongodb-atlas-search
Вопрос:
Я работаю над функцией, которая помогает мне находить похожие документы, отсортированные по количеству баллов, используя функцию полнотекстового поиска MongoDB Atlas.
Я установил индекс своей коллекции как «динамический».
Я ищу сходства в текстовых полях, таких как «имя» или «описание», но я также хочу посмотреть в другом поле «тематическое», в котором хранятся целочисленные значения (идентификаторы) тематики.
Пример:
Допустим, у меня есть справочный документ следующего содержания:
{
name: "test",
description: "It's a glorious day!",
thematic: [9, 3, 2, 33]
}
Я хочу, чтобы мой поиск соответствовал этим int
в тематическом поле и включал их вес в расчет баллов.
Например, если я сравниваю свой справочный документ с :
{
name: "test2",
description: "It's a glorious night!",
thematic: [9, 3, 6, 22]
}
Я хочу увеличить оценку, поскольку тематическое поле разделяет значения 9
и 3
со справочным документом.
Вопрос:
Какой оператор поиска я должен использовать для достижения этой цели? Я могу вводить массив строк в виде запросов с text
помощью оператора, но я не знаю, как работать с целыми числами.
Должен ли я использовать другой подход? Например, разбить массив для сравнения на несколько compound.should.term
запросов?
Редактировать:
После изрядного поиска я нашел это здесь и здесь:
Atlas Search не может индексировать числовые значения или значения даты, если они являются частью массива.
Прежде чем я рассмотрю возможность изменения всей структуры данных моих объектов, я хотел убедиться, что обходного пути нет.
Например, можно ли это сделать с помощью пользовательских анализаторов?
Ответ №1:
Я решил это, добавив триггер в свою коллекцию. Каждый раз, когда документ вставляется или обновляется, я обновляю thematic
и другие аналогичные поля, например _thematic
, где я сохраняю строковое значение целых чисел. Затем я использую это _thematic
поле для поиска.
Вот пример кода, демонстрирующий это:
exports = function (changeEvent) {
const fullDocument = changeEvent.fullDocument;
const format = (itemSet) => {
let rst = [];
Object.keys(itemSet).forEach(item => rst.push(itemSet[item].toString()));
return rst;
};
let setter = {
_thematic: fullDocument.thematic ? format(fullDocument.thematic) : [],
};
const docId = changeEvent.documentKey._id;
const collection = context.services.get("my-cluster").db("dev").collection("projects");
const doc = collection.findOneAndUpdate({ _id: docId },
{ $set: setter });
return;
};
Я почти уверен, что это можно сделать более чистым способом, поэтому, если кто-нибудь опубликует его, я переключу выбранный ответ на него / ее.
Другой способ решить эту проблему — создать пользовательский анализатор с отображением символов, который заменит каждую цифру на ее строковый аналог. Я не пробовал это. См https://docs.atlas.mongodb.com/reference/atlas-search/analyzers/custom/#mapping
Альтернативы приветствуются!