🔎 Added a searchIssue endpoint
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
const mongoose = require("mongoose");
|
const mongoose = require("mongoose");
|
||||||
var mexp = require("mongoose-elasticsearch-xp").v7;
|
var mexp = require("mongoose-elasticsearch-xp").v7;
|
||||||
const paginate = require("mongoose-paginate-v2");
|
const paginate = require("mongoose-paginate-v2");
|
||||||
|
|
||||||
const { Client } = require("@elastic/elasticsearch");
|
const { Client } = require("@elastic/elasticsearch");
|
||||||
|
|
||||||
export const eSClient = new Client({
|
export const eSClient = new Client({
|
||||||
|
|||||||
78
models/comicvine.metadata.model.ts
Normal file
78
models/comicvine.metadata.model.ts
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
const Things = mongoose.Schema({
|
||||||
|
api_detail_url: String,
|
||||||
|
id: Number,
|
||||||
|
name: String,
|
||||||
|
site_detail_url: String,
|
||||||
|
count: String,
|
||||||
|
});
|
||||||
|
const Issue = mongoose.Schema({
|
||||||
|
api_detail_url: String,
|
||||||
|
id: Number,
|
||||||
|
name: String,
|
||||||
|
issue_number: String,
|
||||||
|
});
|
||||||
|
const VolumeInformation = mongoose.Schema({
|
||||||
|
aliases: Array,
|
||||||
|
api_detail_url: String,
|
||||||
|
characters: [Things],
|
||||||
|
concepts: [Things],
|
||||||
|
count_of_issues: String,
|
||||||
|
date_added: String,
|
||||||
|
date_last_updated: String,
|
||||||
|
deck: String,
|
||||||
|
description: String,
|
||||||
|
first_issue: Issue,
|
||||||
|
id: Number,
|
||||||
|
image: {
|
||||||
|
icon_url: String,
|
||||||
|
medium_url: String,
|
||||||
|
screen_url: String,
|
||||||
|
screen_large_url: String,
|
||||||
|
small_url: String,
|
||||||
|
super_url: String,
|
||||||
|
thumb_url: String,
|
||||||
|
tiny_url: String,
|
||||||
|
original_url: String,
|
||||||
|
image_tags: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
issues: [
|
||||||
|
{
|
||||||
|
api_detail_url: String,
|
||||||
|
id: Number,
|
||||||
|
name: String,
|
||||||
|
issue_number: String,
|
||||||
|
site_detail_url: String,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
last_issue: Issue,
|
||||||
|
locations: [Things],
|
||||||
|
name: String,
|
||||||
|
objects: [Things],
|
||||||
|
people: [Things],
|
||||||
|
publisher: {
|
||||||
|
api_detail_url: String,
|
||||||
|
id: Number,
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
site_detail_url: String,
|
||||||
|
start_year: String,
|
||||||
|
});
|
||||||
|
|
||||||
|
const ComicVineMetadata = mongoose.Schema({
|
||||||
|
aliases: [String],
|
||||||
|
api_detail_url: String,
|
||||||
|
cover_date: String,
|
||||||
|
date_added: String,
|
||||||
|
date_last_updated: String,
|
||||||
|
deck: String,
|
||||||
|
description: String,
|
||||||
|
has_staff_review: Boolean,
|
||||||
|
id: Number,
|
||||||
|
name: String,
|
||||||
|
resource_type: String,
|
||||||
|
volumeInformation: VolumeInformation,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ComicVineMetadata;
|
||||||
@@ -142,7 +142,7 @@ export default class ImportService extends Service {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on("end", () => {
|
.on("end", () => {
|
||||||
console.log("Import process complete.");
|
console.log("All files traversed.");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -164,6 +164,9 @@ export default class ImportService extends Service {
|
|||||||
rawFileDetails: {
|
rawFileDetails: {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
acquisition: {
|
||||||
|
wanted: boolean;
|
||||||
|
};
|
||||||
}>
|
}>
|
||||||
) {
|
) {
|
||||||
let volumeDetails;
|
let volumeDetails;
|
||||||
@@ -305,11 +308,16 @@ export default class ImportService extends Service {
|
|||||||
getComicBooks: {
|
getComicBooks: {
|
||||||
rest: "POST /getComicBooks",
|
rest: "POST /getComicBooks",
|
||||||
params: {},
|
params: {},
|
||||||
async handler(ctx: Context<{ paginationOptions: object }>) {
|
async handler(
|
||||||
return await Comic.paginate(
|
ctx: Context<{
|
||||||
{},
|
paginationOptions: object;
|
||||||
ctx.params.paginationOptions
|
predicate: object;
|
||||||
);
|
}>
|
||||||
|
) {
|
||||||
|
return await Comic.paginate(ctx.params.predicate, {
|
||||||
|
...ctx.params.paginationOptions,
|
||||||
|
allowDiskUse: true,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getComicBookById: {
|
getComicBookById: {
|
||||||
@@ -338,26 +346,30 @@ export default class ImportService extends Service {
|
|||||||
rest: "GET /getComicBookGroups",
|
rest: "GET /getComicBookGroups",
|
||||||
params: {},
|
params: {},
|
||||||
async handler(ctx: Context<{}>) {
|
async handler(ctx: Context<{}>) {
|
||||||
let volumesMetadata = [];
|
|
||||||
// 1. get volumes with issues mapped where issue count > 2
|
// 1. get volumes with issues mapped where issue count > 2
|
||||||
const volumes = await Comic.aggregate([
|
const volumes = await Comic.aggregate([
|
||||||
{
|
{
|
||||||
$group: {
|
$project: {
|
||||||
_id: "$sourcedMetadata.comicvine.volume",
|
volumeInfo:
|
||||||
comicBookObjectId: {
|
"$sourcedMetadata.comicvine.volumeInformation",
|
||||||
$last: "$_id",
|
|
||||||
},
|
},
|
||||||
count: { $sum: 1 },
|
},
|
||||||
data: {
|
{
|
||||||
$push: "$$ROOT.sourcedMetadata.comicvine.volumeInformation",
|
$unwind: "$volumeInfo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$group: {
|
||||||
|
_id: "$_id",
|
||||||
|
|
||||||
|
volumes: {
|
||||||
|
$addToSet: "$volumeInfo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
$match: {
|
$unwind: "$volumes",
|
||||||
count: { $gte: 1 },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{ $sort: { updatedAt: -1 } },
|
{ $sort: { updatedAt: -1 } },
|
||||||
{ $skip: 0 },
|
{ $skip: 0 },
|
||||||
{ $limit: 5 },
|
{ $limit: 5 },
|
||||||
@@ -498,10 +510,10 @@ export default class ImportService extends Service {
|
|||||||
$match: {
|
$match: {
|
||||||
"sourcedMetadata.comicInfo": {
|
"sourcedMetadata.comicInfo": {
|
||||||
$exists: true,
|
$exists: true,
|
||||||
$gt: {$size: 0}
|
$gt: { $size: 0 },
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
publisherWithMostComicsInLibrary: [
|
publisherWithMostComicsInLibrary: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,16 +72,6 @@ export default class QueueService extends Service {
|
|||||||
const result = await extractCoverFromFile2(
|
const result = await extractCoverFromFile2(
|
||||||
job.data.fileObject
|
job.data.fileObject
|
||||||
);
|
);
|
||||||
const { filePath } = job.data.fileObject;
|
|
||||||
// get the file constituents and check for comicinfo.xml
|
|
||||||
// If present, convert the xml into json
|
|
||||||
// Import it into mongo
|
|
||||||
const {
|
|
||||||
extension,
|
|
||||||
fileNameWithoutExtension,
|
|
||||||
} = getFileConstituents(filePath);
|
|
||||||
const targetDirectory = `${USERDATA_DIRECTORY}/covers/${fileNameWithoutExtension}`;
|
|
||||||
const info = await extractComicInfoXMLFromArchive(filePath, targetDirectory, extension);
|
|
||||||
|
|
||||||
// infer any issue-related metadata from the filename
|
// infer any issue-related metadata from the filename
|
||||||
const { inferredIssueDetails } = refineQuery(result.name);
|
const { inferredIssueDetails } = refineQuery(result.name);
|
||||||
@@ -104,9 +94,14 @@ export default class QueueService extends Service {
|
|||||||
issue: inferredIssueDetails,
|
issue: inferredIssueDetails,
|
||||||
},
|
},
|
||||||
sourcedMetadata: {
|
sourcedMetadata: {
|
||||||
comicInfo: info,
|
comicInfo: {},
|
||||||
comicvine: {},
|
comicvine: {},
|
||||||
},
|
},
|
||||||
|
// since we already have at least 1 copy
|
||||||
|
// mark it as not wanted by default
|
||||||
|
acquisition: {
|
||||||
|
wanted: false,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
|
|
||||||
import { DbMixin } from "../mixins/db.mixin";
|
import { DbMixin } from "../mixins/db.mixin";
|
||||||
import Comic from "../models/comic.model";
|
import Comic from "../models/comic.model";
|
||||||
import { flatten } from "lodash";
|
import { flatten, isEmpty, isUndefined } from "lodash";
|
||||||
import { eSClient } from "../models/comic.model";
|
import { eSClient } from "../models/comic.model";
|
||||||
const s = eSClient.helpers.msearch();
|
const s = eSClient.helpers.msearch();
|
||||||
|
|
||||||
@@ -64,25 +64,38 @@ export default class SettingsService extends Service {
|
|||||||
params: {},
|
params: {},
|
||||||
handler: async (
|
handler: async (
|
||||||
ctx: Context<{
|
ctx: Context<{
|
||||||
queryObject: {
|
query: {
|
||||||
volumeName: string;
|
volumeName: string;
|
||||||
issueNumber: string;
|
issueNumber: string;
|
||||||
};
|
};
|
||||||
}>
|
}>
|
||||||
) => {
|
) => {
|
||||||
console.log(ctx.params);
|
console.log(ctx.params.query);
|
||||||
const result = await eSClient.search({
|
let eSQuery = {};
|
||||||
index: "comics",
|
if (isEmpty(ctx.params.query)) {
|
||||||
body: {
|
Object.assign(eSQuery, {
|
||||||
query: {
|
match_all: {},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Object.assign(eSQuery, {
|
||||||
match: {
|
match: {
|
||||||
"rawFileDetails.name":
|
"rawFileDetails.name":
|
||||||
ctx.params.queryObject
|
ctx.params.query.volumeName,
|
||||||
.volumeName,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
console.log("eSQuery", eSQuery);
|
||||||
|
const result = await eSClient.search(
|
||||||
|
{
|
||||||
|
index: "comics",
|
||||||
|
body: {
|
||||||
|
query: eSQuery,
|
||||||
|
},
|
||||||
|
size: 50,
|
||||||
|
},
|
||||||
|
{ hydrate: true }
|
||||||
|
);
|
||||||
|
console.log(result.body)
|
||||||
const { hits } = result.body;
|
const { hits } = result.body;
|
||||||
return hits;
|
return hits;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user