Подтвердить что ты не робот

Внедрение полнотекстового поиска MongoDB 2.4 в приложении Meteor

Я ищу добавление полного текстового поиска в приложение Meteor. Я знаю, что MongoDB теперь поддерживает эту функцию, но у меня есть несколько вопросов о реализации:

  • Какой лучший способ включить функцию текстового поиска (textSearchEnabled=true) в приложении Meteor?
  • Есть ли способ добавить индекс (db.collection.ensureIndex()) из вашего приложения?
  • Как вы можете запустить команду Mongo (т.е. db.quotes.runCommand( "text", { search: "TOMORROW" } )) из приложения Meteor?

Поскольку моя цель - добавить поиск в Telescope, я ищу реализацию "plug-and-play", которая требует минимальной команды и может даже работать на Heroku или *.meteor.com.

4b9b3361

Ответ 1

Самый простой способ без редактирования какого-либо кода Метеор - использовать свой собственный mongodb. Ваш mongodb.conf должен выглядеть примерно так (в Arch Linux он находится в /etc/mongodb.conf)

bind_ip = 127.0.0.1
quiet = true
dbpath = /var/lib/mongodb
logpath = /var/log/mongodb/mongod.log
logappend = true
setParameter = textSearchEnabled=true

Ключевая строка setParameter = textSearchEnabled=true, которая, как она заявляет, включает текстовый поиск.

Запустите mongod вверх

Сообщите метеору, чтобы использовать mongod не свой собственный, указав переменную окружения MONGO_URL.

MONGO_URL="mongodb://localhost:27017/meteor" meteor

Теперь скажите, что у вас есть коллекция под названием Dinosaurs, объявленная в collections/dinosaurs.js

Dinosaurs = new Meteor.Collection('dinosaurs');

Чтобы создать текстовый индекс для коллекции, создайте файл server/indexes.js

Meteor.startUp(function () {
    search_index_name = 'whatever_you_want_to_call_it_less_than_128_characters'

    // Remove old indexes as you can only have one text index and if you add 
    // more fields to your index then you will need to recreate it.
    Dinosaurs._dropIndex(search_index_name);

    Dinosaurs._ensureIndex({
        species: 'text',
        favouriteFood: 'text'
    }, {
        name: search_index_name
    });
});

Затем вы можете открыть поиск через Meteor.method, например, в файле server/lib/search_dinosaurs.js.

// Actual text search function
_searchDinosaurs = function (searchText) {
    var Future = Npm.require('fibers/future');
    var future = new Future();
    Meteor._RemoteCollectionDriver.mongo.db.executeDbCommand({
        text: 'dinosaurs',
        search: searchText,
        project: {
          id: 1 // Only take the ids
        }
     }
     , function(error, results) {
        if (results && results.documents[0].ok === 1) {
            future.ret(results.documents[0].results);
        }
        else {
            future.ret('');
        }
    });
    return future.wait();
};

// Helper that extracts the ids from the search results
searchDinosaurs = function (searchText) {
    if (searchText && searchText !== '') {
        var searchResults = _searchEnquiries(searchText);
        var ids = [];
        for (var i = 0; i < searchResults.length; i++) {
            ids.push(searchResults[i].obj._id);
        }
        return ids;
    }
};

Затем вы можете публиковать только те документы, которые были найдены в 'server/publications.js'

Meteor.publish('dinosaurs', function(searchText) {
    var doc = {};
    var dinosaurIds = searchDinosaurs(searchText);
    if (dinosaurIds) {
        doc._id = {
            $in: dinosaurIds
        };
    }
    return Dinosaurs.find(doc);
});

И подписка на стороне клиента будет выглядеть примерно так: client/main.js

Meteor.subscribe('dinosaurs', Session.get('searchQuery'));

Реквизиты Timo Brinkmann, проект musiccrawler был источником большинства этих знаний.

Ответ 2

Чтобы создать текстовый индекс и попытаться добавить его, я надеюсь, что это будет полезно, если есть еще проблема с комментарием

Из docs.mongodb.org:


Добавить скалярные поля индекса в текстовый индекс, как в следующем пример, который указывает возрастающий индексный ключ на имя пользователя:

db.collection.ensureIndex( { comments: "text",
                             username: 1 } )

Предупреждение. Вы не можете включать многоиндексное поле индекса или геопространственный индекс поле.

Используйте параметр проекта в тексте, чтобы возвращать только поля в index, как показано ниже:

db.quotes.runCommand( "text", { search: "tomorrow",
                                project: { username: 1,
                                           _id: 0
                                         }
                              }
                    )

Примечание. По умолчанию поле _id включено в набор результатов. Поскольку индекс примера не содержит поля _id, вы должны явно исключить поле в документе проекта.