我试图更新我的REST API以使用elasticsearch,我发现mongoosastic插件似乎是最好的解决方案,但我找不到如何将Elasticsearch与节点服务器连接的方法。
根据mongoosastic doc(https://github.com/mongoosastic/mongoosastic),user.model.ts中的代码应该可以工作,但是当我创建用户然后点击http://localhost:9200/user/user/_search时,主体为以下json:
{
"error": {
"root_cause": [{
"type": "index_not_found_exception",
"reason": "no such index",
"resource.type": "index_or_alias",
"resource.id": "user",
"index_uuid": "_na_",
"index": "user"
}],
"type": "index_not_found_exception",
"reason": "no such index",
"resource.type": "index_or_alias",
"resource.id": "user",
"index_uuid": "_na_",
"index": "user"
},
"status": 404
}
创建新用户时,控制台中出现以下错误:
POST http://0.0.0.0:9200/users/user/5b9e535a6a2a4100cb86e9a3?refresh=true => connect ECONNREFUSED 0.0.0.0:9200
at Log.error (/app/node_modules/elasticsearch/src/lib/log.js:226:56)
at checkRespForFailure (/app/node_modules/elasticsearch/src/lib/transport.js:259:18)
at HttpConnector.<anonymous> (/app/node_modules/elasticsearch/src/lib/connectors/http.js:163:7)
at ClientRequest.wrapper (/app/node_modules/elasticsearch/node_modules/lodash/lodash.js:4949:19)
at ClientRequest.emit (events.js:182:13)
at Socket.socketErrorListener (_http_client.js:391:9)
at Socket.emit (events.js:182:13)
at emitErrorNT (internal/streams/destroy.js:82:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
at process._tickCallback (internal/process/next_tick.js:63:19)
::ffff:172.18.0.1 - - [16/Sep/2018:12:58:02 +0000] "POST /api/v0/user/ HTTP/1.1" 201 230 "http://localhost:9000/doc/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.92 Safari/537.36"
Elasticsearch WARNING: 2018-09-16T12:58:02Z
Unable to revive connection: http://0.0.0.0:9200/
Elasticsearch WARNING: 2018-09-16T12:58:02Z
No living connections
所以我相信错误只是我配置错误的一些配置选项,但我无法找出做错了什么。
通过浏览器转到http://localhost:9200/_cluster/health,给我:
{
"cluster_name": "docker-cluster",
"status": "yellow",
"timed_out": false,
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 1,
"active_shards": 1,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 1,
"delayed_unassigned_shards": 0,
"number_of_pending_tasks": 0,
"number_of_in_flight_fetch": 0,
"task_max_waiting_in_queue_millis": 0,
"active_shards_percent_as_number": 50.0
}
我也使用docker。
Dockerfile:
FROM mhart/alpine-node:10
ADD . /app
WORKDIR /app
RUN apk --no-cache add --virtual builds-deps build-base python &&\
yarn global add nodemon &&\
yarn &&\
apk del builds-deps build-base python
docker-compose.yml:
version: "3.3"
services:
api:
build: .
links:
- 'mongo:mongo'
- 'elasticsearch:elasticsearch'
env_file:
- .env
volumes:
- .:/app
- /app/node_modules
ports:
- "0.0.0.0:9000:9000"
command: sh -c "mkdir -p dist && touch ./dist/app.js && yarn run start"
transpiler:
build: .
volumes:
- .:/app
- /app/node_modules
command: yarn run transpile -- -w
linter:
build: .
volumes:
- .:/app
- /app/node_modules
command: nodemon --delay 500ms --exec yarn run lint
mongo:
image: mongo:4.0
ports:
- "27017"
command: mongod
volumes:
- ./data:/data/db
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:6.1.1
volumes:
- ./esdata:/esdata
environment:
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- discovery.type=single-node
ports:
- "9300:9300"
- "9200:9200"
mocha:
build: .
volumes:
- .:/app
- /app/node_modules
links:
- 'mongo:mongo'
command: nodemon --delay 500ms --exec yarn run test
env_file:
- .env
environment:
NODE_ENV: 'test'
user.model.ts
import * as mongoose from 'mongoose'
import * as mongoosastic from 'mongoosastic'
import * as elasticsearch from 'elasticsearch'
import * as bcrypt from 'bcrypt'
import * as emailValidator from 'email-validator'
import { IImage, Image } from '../image/image.model'
import config from '../../config/environment'
import { NextFunction } from 'express'
import * as beautifyUnique from 'mongoose-beautiful-unique-validation'
const SALT_WORK_FACTOR: number = config.bcryptWorkFactor
export interface IUser extends mongoose.Document {
mail: string
password: string
login: string
profilPic: mongoose.Types.ObjectId
public: {
mail: string
profilPic: mongoose.Types.ObjectId
login: string
}
}
const UserSchema: mongoose.Schema = new mongoose.Schema({
login: {
required: true,
type: String,
unique: 'Le nom d\'utilisateur `{VALUE}` est déjà utilisé'
},
mail: {
required: true,
type: String,
unique: 'Le mail `{VALUE}` est déjà utilisé'
},
password: { required: true, type: String, select: false },
profilPic: { type: mongoose.Schema.Types.ObjectId, ref: 'Image' },
}, { timestamps: true })
UserSchema.virtual('public').get(function (): object {
return {
id: this.id,
mail: this.mail,
profilPic: this.profilPic,
login: this.login,
}
})
UserSchema.pre<IUser>('save', function (next: NextFunction): void {
// If user already have a picture no need to set the default one
if (this.profilPic) {
return next()
}
const imgProfil: IImage = new Image({
name: 'default.png',
link: config.assetsURI + 'user/profil/default.png',
type: 'png',
width: 502,
height: 502,
})
Image.create(imgProfil).then((img: IImage) => {
this.profilPic = img.id
return next()
}).catch((error: Error) => {
return next(error)
})
})
UserSchema.method('comparePassword',
(password: string, hash: string): Promise<boolean> => {
return bcrypt.compare(password, hash)
.then((value: boolean) => {
return value
})
})
UserSchema.method('hashPassword',
(password: string): Promise<string> => {
return bcrypt.hash(password, SALT_WORK_FACTOR)
.then((hashedPassword: string) => {
return hashedPassword
})
})
UserSchema.static('validEmail', (email: string): boolean => {
return emailValidator.validate(email)
})
UserSchema.set('toJSON', {
transform: (doc: IUser, ret: IUser): void => {
ret.id = ret._id
delete ret._id
delete ret.__v
}
})
UserSchema.plugin(beautifyUnique)
const esClient: elasticsearch.Client = new elasticsearch.Client({
host: '0.0.0.0:9200'
})
UserSchema.plugin(mongoosastic, {
esClient: esClient
})
export const User: mongoose.Model<IUser> =
mongoose.model<IUser>('User', UserSchema)
答案 0 :(得分:1)
您应该将此配置为可配置,并使用Docker内部DNS在主机之间进行通信。
在您的JavaScript代码中,最直接的操作是使用环境变量
const esClient: elasticsearch.Client = new elasticsearch.Client({
host: process.env.ELASTICSEARCH_HOST
})
在开发代码时(本地,在Docker外部),您可以测试一个Elasticsearch(如果需要,可以在容器中)并设置ELASTICSEARCH_HOST=localhost:9200
。部署它时,可以在docker-compose.yml
中设置环境变量:
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:6.1.1
et: cetera
api:
build: .
environment:
ELASTICSEARCH_HOST: 'elasticsearch:9200'
env_file:
- .env
ports:
- "0.0.0.0:9000:9000"
(您不再需要links:
;它没有害处,但是它不必要地冗长。我会使用Dockerfile
在图像中安装应用程序代码并设置默认命令。)