Implementing MongoDB 2.4's full text search in a Meteor app

后端 未结 2 1509
暗喜
暗喜 2021-01-30 13:40

I\'m looking into adding full text search to a Meteor app. I know MongoDB now supports this feature, but I have a few questions about the implementation:

  • What\'s t
相关标签:
2条回答
  • 2021-01-30 13:54

    The simplest way without editing any Meteor code is to use your own mongodb. Your mongodb.conf should look something like this (on Arch Linux it is found at /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
    

    The key line is setParameter = textSearchEnabled=true, which, as it states, enables text search.

    Start mongod up

    Tell meteor to use your mongod not its own by specifying the MONGO_URL environmental variable.

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

    Now say you have collection called Dinosaurs declared say in collections/dinosaurs.js

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

    To create an text index for the collection create a file 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
        });
    });
    

    Then you can expose the search through a Meteor.method, for example in the file 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;
        }
    };
    

    Then you can publish only documents that have been searched for in 'server/publications.js'

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

    And the client side subscription would look something like this in client/main.js

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

    Props to Timo Brinkmann whose musiccrawler project was the source of most this knowledge.

    0 讨论(0)
  • 2021-01-30 14:05

    To create a text index and try to add like this I hope so it will be useful if there is still problem comment

    From docs.mongodb.org:


    Append scalar index fields to a text index, as in the following example which specifies an ascending index key on username:

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

    Warning You cannot include multi-key index field or geospatial index field.

    Use the project option in the text to return only the fields in the index, as in the following:

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

    Note: By default, the _id field is included in the result set. Since the example index did not include the _id field, you must explicitly exclude the field in the project document.

    0 讨论(0)
提交回复
热议问题