NestJS - 从 POST 请求获取响应 body 并用另一种方法将其保存到 mongoDB
NestJS - get response body from POST request and save it to mongoDB in another method
在调用一个 POST 请求后,我正在尝试从 1 个响应 body 中获得响应 body(并且我成功了),然后我也想保存它到 Mongo 数据库。但问题是它实际上并没有保存它(可能是因为 Mongoose)并且它没有使用想要的 body,只是保存了“ID”。
这里是controller(装饰器@Post('scrape/:id'))
import { Body, Controller, Get, Post, Param, Res } from '@nestjs/common';
import { CreateBooleanStringDto } from '../dto/handles/create-boolean.dto';
import { CreateRawHandlesDto } from '../dto/handles/createRawHandlesDto';
import { HandlesService } from './handles.service';
import { BooleanString } from './interfaces/booleanString.interface';
import { RawHandles } from './interfaces/rawHandles.interface';
@Controller('booleans')
export class HandlesController {
constructor(private readonly handlesService: HandlesService) {}
@Get()
async findAll(): Promise<BooleanString[]> {
return await this.handlesService.findAll();
}
@Get(':id')
async findOne(@Param('id') id): Promise<BooleanString> {
return await this.handlesService.findOne(id);
}
@Post()
create(@Body() createBooleanStringDto: CreateBooleanStringDto): Promise<BooleanString> {
return this.handlesService.create(createBooleanStringDto)
}
@Post('scrape/:id')
async getBoolean(@Param('id') id, @Body() createRawHandlesDto: CreateRawHandlesDto): Promise<CreateRawHandlesDto> {
let term = await this.handlesService.getBoolean(id);
let handles = await this.handlesService.scrapeHandles([term.value]);
await this.handlesService.saveRawHandles(handles)
return handles;
}
@Post('map/:id')
async mapWriteHandles(@Param('id') id){
let booleanObject = await this.handlesService.getBoolean(id);
console.log(booleanObject)
return await this.handlesService.mapWriteHandles('https://linkedin', booleanObject.groupName)
}
}
服务(方法scrapeHandles returns结果我需要在方法saveRawHandles中保存到Mongo
import { Injectable, Logger} from '@nestjs/common';
import { BooleanString } from './interfaces/booleanString.interface';
import { CreateRawHandlesDto } from '../dto/handles/createRawHandlesDto';
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { writeFile, readFileSync } from 'fs';
import { RawHandles } from './interfaces/rawHandles.interface';
@Injectable()
export class HandlesService {
private readonly logger = new Logger(HandlesService.name);
constructor(
@InjectModel('BooleanString')
private readonly booleanStringModel: Model<BooleanString>,
@InjectModel('RawHandles')
private readonly rawHandlesModel: Model<RawHandles>
) {}
async findAll(): Promise<BooleanString[]> {
return await this.booleanStringModel.find();
}
async findOne(id: string): Promise<BooleanString> {
return await this.booleanStringModel.findOne({ _id: id });
}
async create(booleanString: BooleanString): Promise<BooleanString> {
const newBoolean = new this.booleanStringModel(booleanString);
return await newBoolean.save();
}
async getBoolean(id: string): Promise<BooleanString> {
const booleanObject = await this.booleanStringModel.findOne({ _id: id });
const booleanStringValue = booleanObject.value;
return await this.booleanStringModel.findOne({ _id: id });
}
async scrapeHandles(booleanString): Promise<any> {
const se_scraper = require('se-scraper'); //
const scrape_job = {
search_engine: 'bing',
keywords: booleanString,
num_pages: 50,
};
const results = await se_scraper.scrape({}, scrape_job);
this.logger.log('Puppeter finished scraping handles from Bing')
return results;
}
async saveRawHandles(createRawHandlesDto: CreateRawHandlesDto): Promise<RawHandles> {
const createdRawHandles = new this.rawHandlesModel(createRawHandlesDto);
const dupa = new this.rawHandlesModel
return createdRawHandles.save();
}
async mapWriteHandles(uriToReplace, groupName): Promise<any> {
const fileToMap = require('../output/rawHandlesFromBing.json');
const handles = [];
const mapHandles = (uriToReplace) => {
const scrapedProspect = fileToMap.results.results;
Object.keys(scrapedProspect).forEach((key) => {
const resultPage = scrapedProspect[key];
Object.keys(resultPage).forEach((key) => {
const results = resultPage[key].results;
results.forEach((x) => {
const link = x.link.replace(uriToReplace, '');
handles.push(link);
});
});
});
};
const writeHandlesToFile = (groupName) => {
const obj = { groupName, handles };
const jsonOutput = JSON.stringify(obj);
console.log(obj);
writeFile('handles.json', jsonOutput, (err) => {
if (err) console.log(err);
else console.log('success');
});
};
const main = (uriToReplace, groupName) => {
mapHandles(uriToReplace);
writeHandlesToFile(groupName);
};
}
}
rawHandles 接口
export interface RawHandles {
id?: string,
booleanID: string,
results: any
}
rawHandles DTO
export class CreateRawHandlesDto {
readonly booleanID: string;
readonly results: any;
}
示例 JSON object (results) 我想保存到 rawHandles in [=73] =]
{
"results": {
"Backend AND Python developer": {
"1": {
"num_results": "Wyniki: 7 000 000",
"no_results": false,
"effective_query": "",
"results": [
{
"link": "https://www.pythonistaplanet.com/how-to-become-a-python-backend-developer/#:~:text=To%20become%20a%20Python%20backend%20developer%2C%20first%20of,to%20have%20a%20basic%20understanding%20of%20front-end%20technologies.",
"title": "How To Become A Python Back-End Developer – Pythonista Planet",
"snippet": "",
"visible_link": "",
"rank": 1
},
{
"link": "https://code-maven.com/backend-python-developer",
"title": "Backend Python developer - Junior Python …",
"snippet": "11.03.2020 · A large subset of backend developers write web applications. They need to know the appropriate web framework used at their company. There are many Python-based web frameworks, but the most popular ones are Django and Flask. Learn at least one of them to increase your chances to become a good backend developer. Hint: Flask is much easire to learn.",
"visible_link": "https://code-maven.com/backend-python-developer",
"rank": 2
},
"metadata": {
"scraping_detected": false,
"elapsed_time": "16289",
"ms_per_keyword": "325.78",
"num_requests": 50
}
}
编辑:
我一直在尝试做一些不同但仍然没有成功,我不知道如何将它传递给 saveRawHandles() 方法并使用 Mongoose 将其保存到 Mongo。这是控制器和服务的最新代码
控制器:
@Post('scrape/:id')
async getBoolean(@Param('id') id, @Body() createRawHandlesDto: CreateRawHandlesDto): Promise<CreateRawHandlesDto> {
let term = await this.handlesService.getBoolean(id);
let handles = await this.handlesService.scrapeHandles([term.value]);
let rawHandles = {
booleanID: term.id,
results: handles
}
console.log(rawHandles)
await this.handlesService.saveRawHandles(rawHandles)
return handles;
}
console.log (json object rawHandles)
{
booleanID: '60c8c4a481c9af67bf6c874a',
results: {
results: { 'Backend AND Python developer': [Object] },
metadata: {
scraping_detected: false,
elapsed_time: '15934',
ms_per_keyword: '318.68',
num_requests: 50
}
}
服务
async saveRawHandles(createRawHandlesDto: CreateRawHandlesDto): Promise<RawHandles> {
const createdRawHandles = new this.rawHandlesModel(createRawHandlesDto);
return createdRawHandles.save();
}
这是来自 Mongodb in cloud 的屏幕截图,基本上它只是添加新的 objects 但不是按照模式
MongoDB CLoud screenshoot
终于解决了。朋友建议我不要使用 Mongoose,因为它是某种 TypeORM (ODM),而只使用 Mongo,它是 API。所以我所做的是使用 Provider:
mondo.module.ts
import { Module } from '@nestjs/common';
import { MongoClient, Db } from 'mongodb';
@Module({
providers: [
{
provide: 'DATABASE_CONNECTION',
useFactory: async (): Promise<Db> => {
try {
const client = await MongoClient.connect(
process.env.MONGO_CONNECTION,
{
useUnifiedTopology: true,
auth: {
user: process.env.MONGO_USER,
password: process.env.MONGO_PASSWORD,
},
},
);
return client.db();
} catch (e) {
throw e;
}
},
},
],
exports: ['DATABASE_CONNECTION'],
})
export class DatabaseModule {}
然后将其导入到您的模块中。
handless.module.ts
import { DatabaseModule } from '../core/mongo/mongo.module';
@Module({
imports: [
MongooseModule.forFeature([{ name: 'BooleanString', schema: BooleanStringSchema }]),
DatabaseModule
],
controllers: [HandlesController],
providers: [HandlesService],
})
export class HandlesModule {}
现在我们可以在我们的服务中使用它了。这是我完成的一个最小示例,它在我这边工作正常,如我所愿
handless.service.ts
import { Injectable, Logger, Inject } from '@nestjs/common';
import { BooleanString } from './interfaces/booleanString.interface';
import { Model } from 'mongoose';
import { Db, Collection } from 'mongodb';
import { InjectModel } from '@nestjs/mongoose';
import { writeFile } from 'fs';
@Injectable()
export class HandlesService {
private readonly logger = new Logger(HandlesService.name);
private handlesCollection: Collection<any>;
constructor(
@InjectModel('BooleanString')
private readonly booleanStringModel: Model<BooleanString>,
@Inject('DATABASE_CONNECTION')
private db: Db,
) {
this.handlesCollection = this.db.collection('rawHandles');
}
async scrapeHandles(booleanString): Promise<any> {
const se_scraper = require('se-scraper'); //
const scrape_job = {
search_engine: 'bing',
keywords: booleanString,
num_pages: 50,
};
const results = await se_scraper.scrape({}, scrape_job);
this.logger.log('Puppeter finished scraping handles from Bing')
return results;
}
async saveRawHandles(results): Promise<any> {
return await this.handlesCollection.insertOne(results);
}
和控制器。
handless.controller.ts
import { Body, Controller, Get, Post, Param, Res } from '@nestjs/common';
import { CreateBooleanStringDto } from '../dto/handles/create-boolean.dto';
import { HandlesService } from './handles.service';
import { BooleanString } from './interfaces/booleanString.interface';
@Controller('booleans')
export class HandlesController {
constructor(private readonly handlesService: HandlesService) {}
@Post('scrape/:id')
async getBoolean(@Param('id') id): Promise<any> {
let term = await this.handlesService.getBoolean(id);
let handles = await this.handlesService.scrapeHandles([term.value]);
let results = {
booleanSearchID: term.id,
results: handles
}
await this.handlesService.saveRawHandles(results);
return handles;
}
}
在调用一个 POST 请求后,我正在尝试从 1 个响应 body 中获得响应 body(并且我成功了),然后我也想保存它到 Mongo 数据库。但问题是它实际上并没有保存它(可能是因为 Mongoose)并且它没有使用想要的 body,只是保存了“ID”。
这里是controller(装饰器@Post('scrape/:id'))
import { Body, Controller, Get, Post, Param, Res } from '@nestjs/common';
import { CreateBooleanStringDto } from '../dto/handles/create-boolean.dto';
import { CreateRawHandlesDto } from '../dto/handles/createRawHandlesDto';
import { HandlesService } from './handles.service';
import { BooleanString } from './interfaces/booleanString.interface';
import { RawHandles } from './interfaces/rawHandles.interface';
@Controller('booleans')
export class HandlesController {
constructor(private readonly handlesService: HandlesService) {}
@Get()
async findAll(): Promise<BooleanString[]> {
return await this.handlesService.findAll();
}
@Get(':id')
async findOne(@Param('id') id): Promise<BooleanString> {
return await this.handlesService.findOne(id);
}
@Post()
create(@Body() createBooleanStringDto: CreateBooleanStringDto): Promise<BooleanString> {
return this.handlesService.create(createBooleanStringDto)
}
@Post('scrape/:id')
async getBoolean(@Param('id') id, @Body() createRawHandlesDto: CreateRawHandlesDto): Promise<CreateRawHandlesDto> {
let term = await this.handlesService.getBoolean(id);
let handles = await this.handlesService.scrapeHandles([term.value]);
await this.handlesService.saveRawHandles(handles)
return handles;
}
@Post('map/:id')
async mapWriteHandles(@Param('id') id){
let booleanObject = await this.handlesService.getBoolean(id);
console.log(booleanObject)
return await this.handlesService.mapWriteHandles('https://linkedin', booleanObject.groupName)
}
}
服务(方法scrapeHandles returns结果我需要在方法saveRawHandles中保存到Mongo
import { Injectable, Logger} from '@nestjs/common';
import { BooleanString } from './interfaces/booleanString.interface';
import { CreateRawHandlesDto } from '../dto/handles/createRawHandlesDto';
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { writeFile, readFileSync } from 'fs';
import { RawHandles } from './interfaces/rawHandles.interface';
@Injectable()
export class HandlesService {
private readonly logger = new Logger(HandlesService.name);
constructor(
@InjectModel('BooleanString')
private readonly booleanStringModel: Model<BooleanString>,
@InjectModel('RawHandles')
private readonly rawHandlesModel: Model<RawHandles>
) {}
async findAll(): Promise<BooleanString[]> {
return await this.booleanStringModel.find();
}
async findOne(id: string): Promise<BooleanString> {
return await this.booleanStringModel.findOne({ _id: id });
}
async create(booleanString: BooleanString): Promise<BooleanString> {
const newBoolean = new this.booleanStringModel(booleanString);
return await newBoolean.save();
}
async getBoolean(id: string): Promise<BooleanString> {
const booleanObject = await this.booleanStringModel.findOne({ _id: id });
const booleanStringValue = booleanObject.value;
return await this.booleanStringModel.findOne({ _id: id });
}
async scrapeHandles(booleanString): Promise<any> {
const se_scraper = require('se-scraper'); //
const scrape_job = {
search_engine: 'bing',
keywords: booleanString,
num_pages: 50,
};
const results = await se_scraper.scrape({}, scrape_job);
this.logger.log('Puppeter finished scraping handles from Bing')
return results;
}
async saveRawHandles(createRawHandlesDto: CreateRawHandlesDto): Promise<RawHandles> {
const createdRawHandles = new this.rawHandlesModel(createRawHandlesDto);
const dupa = new this.rawHandlesModel
return createdRawHandles.save();
}
async mapWriteHandles(uriToReplace, groupName): Promise<any> {
const fileToMap = require('../output/rawHandlesFromBing.json');
const handles = [];
const mapHandles = (uriToReplace) => {
const scrapedProspect = fileToMap.results.results;
Object.keys(scrapedProspect).forEach((key) => {
const resultPage = scrapedProspect[key];
Object.keys(resultPage).forEach((key) => {
const results = resultPage[key].results;
results.forEach((x) => {
const link = x.link.replace(uriToReplace, '');
handles.push(link);
});
});
});
};
const writeHandlesToFile = (groupName) => {
const obj = { groupName, handles };
const jsonOutput = JSON.stringify(obj);
console.log(obj);
writeFile('handles.json', jsonOutput, (err) => {
if (err) console.log(err);
else console.log('success');
});
};
const main = (uriToReplace, groupName) => {
mapHandles(uriToReplace);
writeHandlesToFile(groupName);
};
}
}
rawHandles 接口
export interface RawHandles {
id?: string,
booleanID: string,
results: any
}
rawHandles DTO
export class CreateRawHandlesDto {
readonly booleanID: string;
readonly results: any;
}
示例 JSON object (results) 我想保存到 rawHandles in [=73] =]
{
"results": {
"Backend AND Python developer": {
"1": {
"num_results": "Wyniki: 7 000 000",
"no_results": false,
"effective_query": "",
"results": [
{
"link": "https://www.pythonistaplanet.com/how-to-become-a-python-backend-developer/#:~:text=To%20become%20a%20Python%20backend%20developer%2C%20first%20of,to%20have%20a%20basic%20understanding%20of%20front-end%20technologies.",
"title": "How To Become A Python Back-End Developer – Pythonista Planet",
"snippet": "",
"visible_link": "",
"rank": 1
},
{
"link": "https://code-maven.com/backend-python-developer",
"title": "Backend Python developer - Junior Python …",
"snippet": "11.03.2020 · A large subset of backend developers write web applications. They need to know the appropriate web framework used at their company. There are many Python-based web frameworks, but the most popular ones are Django and Flask. Learn at least one of them to increase your chances to become a good backend developer. Hint: Flask is much easire to learn.",
"visible_link": "https://code-maven.com/backend-python-developer",
"rank": 2
},
"metadata": {
"scraping_detected": false,
"elapsed_time": "16289",
"ms_per_keyword": "325.78",
"num_requests": 50
}
}
编辑:
我一直在尝试做一些不同但仍然没有成功,我不知道如何将它传递给 saveRawHandles() 方法并使用 Mongoose 将其保存到 Mongo。这是控制器和服务的最新代码 控制器:
@Post('scrape/:id')
async getBoolean(@Param('id') id, @Body() createRawHandlesDto: CreateRawHandlesDto): Promise<CreateRawHandlesDto> {
let term = await this.handlesService.getBoolean(id);
let handles = await this.handlesService.scrapeHandles([term.value]);
let rawHandles = {
booleanID: term.id,
results: handles
}
console.log(rawHandles)
await this.handlesService.saveRawHandles(rawHandles)
return handles;
}
console.log (json object rawHandles)
{
booleanID: '60c8c4a481c9af67bf6c874a',
results: {
results: { 'Backend AND Python developer': [Object] },
metadata: {
scraping_detected: false,
elapsed_time: '15934',
ms_per_keyword: '318.68',
num_requests: 50
}
}
服务
async saveRawHandles(createRawHandlesDto: CreateRawHandlesDto): Promise<RawHandles> {
const createdRawHandles = new this.rawHandlesModel(createRawHandlesDto);
return createdRawHandles.save();
}
这是来自 Mongodb in cloud 的屏幕截图,基本上它只是添加新的 objects 但不是按照模式 MongoDB CLoud screenshoot
终于解决了。朋友建议我不要使用 Mongoose,因为它是某种 TypeORM (ODM),而只使用 Mongo,它是 API。所以我所做的是使用 Provider:
mondo.module.ts
import { Module } from '@nestjs/common';
import { MongoClient, Db } from 'mongodb';
@Module({
providers: [
{
provide: 'DATABASE_CONNECTION',
useFactory: async (): Promise<Db> => {
try {
const client = await MongoClient.connect(
process.env.MONGO_CONNECTION,
{
useUnifiedTopology: true,
auth: {
user: process.env.MONGO_USER,
password: process.env.MONGO_PASSWORD,
},
},
);
return client.db();
} catch (e) {
throw e;
}
},
},
],
exports: ['DATABASE_CONNECTION'],
})
export class DatabaseModule {}
然后将其导入到您的模块中。 handless.module.ts
import { DatabaseModule } from '../core/mongo/mongo.module';
@Module({
imports: [
MongooseModule.forFeature([{ name: 'BooleanString', schema: BooleanStringSchema }]),
DatabaseModule
],
controllers: [HandlesController],
providers: [HandlesService],
})
export class HandlesModule {}
现在我们可以在我们的服务中使用它了。这是我完成的一个最小示例,它在我这边工作正常,如我所愿 handless.service.ts
import { Injectable, Logger, Inject } from '@nestjs/common';
import { BooleanString } from './interfaces/booleanString.interface';
import { Model } from 'mongoose';
import { Db, Collection } from 'mongodb';
import { InjectModel } from '@nestjs/mongoose';
import { writeFile } from 'fs';
@Injectable()
export class HandlesService {
private readonly logger = new Logger(HandlesService.name);
private handlesCollection: Collection<any>;
constructor(
@InjectModel('BooleanString')
private readonly booleanStringModel: Model<BooleanString>,
@Inject('DATABASE_CONNECTION')
private db: Db,
) {
this.handlesCollection = this.db.collection('rawHandles');
}
async scrapeHandles(booleanString): Promise<any> {
const se_scraper = require('se-scraper'); //
const scrape_job = {
search_engine: 'bing',
keywords: booleanString,
num_pages: 50,
};
const results = await se_scraper.scrape({}, scrape_job);
this.logger.log('Puppeter finished scraping handles from Bing')
return results;
}
async saveRawHandles(results): Promise<any> {
return await this.handlesCollection.insertOne(results);
}
和控制器。 handless.controller.ts
import { Body, Controller, Get, Post, Param, Res } from '@nestjs/common';
import { CreateBooleanStringDto } from '../dto/handles/create-boolean.dto';
import { HandlesService } from './handles.service';
import { BooleanString } from './interfaces/booleanString.interface';
@Controller('booleans')
export class HandlesController {
constructor(private readonly handlesService: HandlesService) {}
@Post('scrape/:id')
async getBoolean(@Param('id') id): Promise<any> {
let term = await this.handlesService.getBoolean(id);
let handles = await this.handlesService.scrapeHandles([term.value]);
let results = {
booleanSearchID: term.id,
results: handles
}
await this.handlesService.saveRawHandles(results);
return handles;
}
}