UNPKG

mongoose-elasticsearch-xp

Version:

A mongoose plugin that indexes models into elastic search (an alternative to mongoosastic)

318 lines (282 loc) 9.68 kB
var utils = require('./utils'); var mongoose = require('mongoose'); var plugin = require('../'); describe("model-mapping", function () { utils.setup(); it('should create an implicit mapping', function (done) { var deepEmbeddedSchema = new mongoose.Schema({ _id: false, dn: Number }); var embeddedSchema = new mongoose.Schema({ _id: false, key: String, deep: [deepEmbeddedSchema] }); var UserSchema = new mongoose.Schema({ name: String, age: Number, joined: Date, optin: {type: Boolean, default: true}, tags: [String], plain: { x: String, y: Number, z: Boolean }, embedded: embeddedSchema }); UserSchema.plugin(plugin); var UserModel = mongoose.model('User', UserSchema); utils.deleteModelIndexes(UserModel) .then(function () { return UserModel.esCreateMapping(); }) .then(function () { var options = UserModel.esOptions(); return options.client.indices.getMapping({ index: options.index, type: options.type }); }) .then(function (mapping) { var properties = mapping.users.mappings.user.properties; expect(properties).to.have.all.keys('name', 'age', 'joined', 'tags', 'optin', 'plain', 'embedded'); expect(properties.name.type).to.be.equal('string'); expect(properties.age.type).to.be.equal('double'); expect(properties.joined.type).to.be.equal('date'); expect(properties.tags.type).to.be.equal('string'); expect(properties.optin.type).to.be.equal('boolean'); expect(properties.plain.properties).to.have.all.keys('x', 'y', 'z'); expect(properties.plain.properties.x.type).to.be.equal('string'); expect(properties.plain.properties.y.type).to.be.equal('double'); expect(properties.plain.properties.z.type).to.be.equal('boolean'); expect(properties.embedded.properties).to.have.all.keys('deep', 'key'); expect(properties.embedded.properties.key.type).to.be.equal('string'); expect(properties.embedded.properties.deep.properties).to.have.all.keys('dn'); expect(properties.embedded.properties.deep.properties.dn.type).to.be.equal('double'); done(); }) .catch(function (err) { done(err); }); }); it('should create an explicit mapping', function (done) { var deepImplicitEmbeddedSchema = new mongoose.Schema({ _id: false, dn: Number }); var embeddedSchema = new mongoose.Schema({ _id: false, key: String, deep1: {type: [deepImplicitEmbeddedSchema], es_indexed: true}, deep2: {type: [deepImplicitEmbeddedSchema]} }); var implicitEmbeddedSchema = new mongoose.Schema({ _id: false, anyKey: String }); var UserSchema = new mongoose.Schema({ name: {type: String, es_indexed: true}, age: Number, joined: {type: Date}, optin: {type: Boolean, default: true, es_indexed: true}, tags: {type: [String], es_indexed: true}, plain: { // plain object so, without es_indexed would not be included x: String, y: Number, z: Boolean }, embedded1: {type: embeddedSchema, es_indexed: false}, // needed, because of embedded1.deep1.es_indexed == true embedded2: {type: embeddedSchema, es_indexed: true}, embedded3: implicitEmbeddedSchema // no explicit es_indexed, so, would not be included }); UserSchema.plugin(plugin); var UserModel = mongoose.model('User', UserSchema); utils.deleteModelIndexes(UserModel) .then(function () { return UserModel.esCreateMapping(); }) .then(function () { var options = UserModel.esOptions(); return options.client.indices.getMapping({ index: options.index, type: options.type }); }) .then(function (mapping) { var properties = mapping.users.mappings.user.properties; expect(properties).to.have.all.keys('name', 'tags', 'optin', 'embedded2'); expect(properties.name.type).to.be.equal('string'); expect(properties.tags.type).to.be.equal('string'); expect(properties.optin.type).to.be.equal('boolean'); expect(properties.embedded2.properties).to.have.all.keys('deep1'); expect(properties.embedded2.properties.deep1.properties).to.have.all.keys('dn'); expect(properties.embedded2.properties.deep1.properties.dn.type).to.be.equal('double'); done(); }) .catch(function (err) { done(err); }); }); it('should propagate es options', function (done) { var UserSchema = new mongoose.Schema({ name: {type: String, es_boost: 2}, age: {type: Number, es_type: 'integer', es_boost: 1.5}, joined: Date, optin: {type: Boolean, default: true}, pos: { type: [Number], index: '2dsphere', es_type: 'geo_point' } }); UserSchema.plugin(plugin); var UserModel = mongoose.model('User', UserSchema); utils.deleteModelIndexes(UserModel) .then(function () { return UserModel.esCreateMapping(); }) .then(function () { var options = UserModel.esOptions(); return options.client.indices.getMapping({ index: options.index, type: options.type }); }) .then(function (mapping) { var properties = mapping.users.mappings.user.properties; expect(properties).to.have.all.keys('name', 'age', 'joined', 'optin', 'pos'); expect(properties.name.type).to.be.equal('string'); expect(properties.name.boost).to.be.equal(2); expect(properties.age.type).to.be.equal('integer'); expect(properties.age.boost).to.be.equal(1.5); expect(properties.joined.type).to.be.equal('date'); expect(properties.optin.type).to.be.equal('boolean'); expect(properties.pos.type).to.be.equal('geo_point'); done(); }) .catch(function (err) { done(err); }); }); // https://www.elastic.co/guide/en/elasticsearch/reference/2.0/nested.html it('should handle nested datatype', function (done) { var UserSchema = new mongoose.Schema({ _id: false, first: String, last: String }); var GroupSchema = new mongoose.Schema({ group: String, user: {type: [UserSchema], es_type: 'nested'} }); GroupSchema.plugin(plugin); var GroupModel = mongoose.model('Group', GroupSchema); utils.deleteModelIndexes(GroupModel) .then(function () { return GroupModel.esCreateMapping(); }) .then(function () { var options = GroupModel.esOptions(); return options.client.indices.getMapping({ index: options.index, type: options.type }); }) .then(function (mapping) { var properties = mapping.groups.mappings.group.properties; expect(properties).to.have.all.keys('group', 'user'); expect(properties.group.type).to.be.equal('string'); expect(properties.user.type).to.be.equal('nested'); expect(properties.user.properties).to.have.all.keys('first', 'last'); expect(properties.user.properties.first.type).to.be.equal('string'); expect(properties.user.properties.last.type).to.be.equal('string'); }) .then(function () { return new utils.Promise(function (resolve, reject) { var group = new GroupModel({ "group": "fans", "user": [ { "first": "John", "last": "Smith" }, { "first": "Alice", "last": "White" } ] }); group.on('es-indexed', function () { resolve(); }); return group.save(); }); }) .then(function () { return GroupModel.esRefresh(); }) .then(function () { return GroupModel .esSearch({ "query": { "nested": { "path": "user", "query": { "bool": { "must": [ { "match": { "user.first": "Alice" }}, { "match": { "user.last": "Smith" }} ] } } } } }) .then(function (result) { expect(result.hits.total).to.eql(0); }); }) .then(function () { return GroupModel .esSearch({ "query": { "nested": { "path": "user", "query": { "bool": { "must": [ { "match": { "user.first": "Alice" }}, { "match": { "user.last": "White" }} ] } } } } }) .then(function (result) { expect(result.hits.total).to.eql(1); expect(result.hits.hits[0]._source).to.eql({ "group": "fans", "user": [ { "first": "John", "last": "Smith" }, { "first": "Alice", "last": "White" } ] }); }); }) .then(function () { done(); }) .catch(function (err) { done(err); }); }); });