forked from geolba/tethys.frontend
Opensearch progress.
- Term search works - Pending faceted search - Ongoing: highlight of fuzzy results
This commit is contained in:
parent
6d1c1b28c3
commit
4f53411d07
|
@ -30,5 +30,5 @@ const post = <T>(url: string, body: any, queryParams?: any): Observable<T> => {
|
||||||
.pipe(map((result: AxiosResponse) => result.data)); // Use map to transform the Axios response to extract the data property
|
.pipe(map((result: AxiosResponse) => result.data)); // Use map to transform the Axios response to extract the data property
|
||||||
};
|
};
|
||||||
|
|
||||||
// Export the get function as part of the default export
|
// Export the get and post functions as part of the default export
|
||||||
export default { get, post };
|
export default { get, post };
|
|
@ -2,16 +2,14 @@
|
||||||
// import debounce from 'lodash/debounce';
|
// import debounce from 'lodash/debounce';
|
||||||
// import { DatasetService } from "../../services/dataset.service";
|
// import { DatasetService } from "../../services/dataset.service";
|
||||||
import DatasetService from "../../services/dataset.service";
|
import DatasetService from "../../services/dataset.service";
|
||||||
import { SolrSettings } from "@/models/solr";
|
import { SolrSettings } from "@/models/solr"; // PENDING USE
|
||||||
|
|
||||||
import { OpenSettings } from "@/models/solr";
|
import { OpenSettings } from "@/models/solr";
|
||||||
// import { ref } from "vue";
|
|
||||||
import { Component, Vue, Prop, Emit } from "vue-facing-decorator";
|
import { Component, Vue, Prop, Emit } from "vue-facing-decorator";
|
||||||
// import { Prop, Emit } from "vue-property-decorator";
|
|
||||||
import { Dataset, Suggestion, SearchType } from "@/models/dataset";
|
import { Dataset, Suggestion, SearchType } from "@/models/dataset";
|
||||||
import { SOLR_HOST, SOLR_CORE } from "@/constants";
|
import { SOLR_HOST, SOLR_CORE } from "@/constants";
|
||||||
|
|
||||||
import { OPEN_HOST, OPEN_CORE } from "@/constants";
|
import { OPEN_HOST, OPEN_CORE } from "@/constants"; // PENDING USE
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
name: "VsInput",
|
name: "VsInput",
|
||||||
|
@ -20,19 +18,20 @@ export default class VsInput extends Vue {
|
||||||
// @Prop()
|
// @Prop()
|
||||||
// private title!: string;
|
// private title!: string;
|
||||||
|
|
||||||
|
// Define the placeholder text for the input field
|
||||||
@Prop({ default: "Search" })
|
@Prop({ default: "Search" })
|
||||||
readonly placeholder!: string;
|
readonly placeholder!: string;
|
||||||
|
|
||||||
private display = "";
|
private display = ""; // Input display value
|
||||||
|
|
||||||
@Prop()
|
@Prop()
|
||||||
private propDisplay = "";
|
private propDisplay = "";
|
||||||
|
|
||||||
private value!: Suggestion | string;
|
private value!: Suggestion | string;
|
||||||
private error = "";
|
private error = "";
|
||||||
private results: Array<Dataset> = [];
|
private results: Array<Dataset> = []; // Array to store search results
|
||||||
private loading = false;
|
private loading = false; // Loading state indicator
|
||||||
private selectedIndex = -1;
|
private selectedIndex = -1; // Index of the currently selected suggestion
|
||||||
// private selectedDisplay = "";
|
// private selectedDisplay = "";
|
||||||
private solr: SolrSettings = {
|
private solr: SolrSettings = {
|
||||||
core: SOLR_CORE, //"rdr_data", // SOLR.core;
|
core: SOLR_CORE, //"rdr_data", // SOLR.core;
|
||||||
|
@ -49,9 +48,10 @@ export default class VsInput extends Vue {
|
||||||
};
|
};
|
||||||
|
|
||||||
// private rdrAPI!: DatasetService;
|
// private rdrAPI!: DatasetService;
|
||||||
itemRefs!: Array<Element>;
|
itemRefs!: Array<Element>; // Array to store references to suggestion items
|
||||||
emits = ["filter"];
|
emits = ["filter"]; // Emits filter event
|
||||||
|
|
||||||
|
// Set reference for each item
|
||||||
setItemRef(el: Element): void {
|
setItemRef(el: Element): void {
|
||||||
this.itemRefs.push(el);
|
this.itemRefs.push(el);
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,7 @@ export default class VsInput extends Vue {
|
||||||
return this.error !== null;
|
return this.error !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Computed property to generate suggestions based on search results
|
||||||
get suggestions(): Suggestion[] {
|
get suggestions(): Suggestion[] {
|
||||||
// const suggestion = {
|
// const suggestion = {
|
||||||
// titles: new Array<string>(),
|
// titles: new Array<string>(),
|
||||||
|
@ -89,12 +90,17 @@ export default class VsInput extends Vue {
|
||||||
const suggestions = new Array<Suggestion>();
|
const suggestions = new Array<Suggestion>();
|
||||||
|
|
||||||
console.log("Display:", this.display);
|
console.log("Display:", this.display);
|
||||||
// console.log("results:", this.results );
|
console.log("results:", this.results );
|
||||||
|
|
||||||
|
|
||||||
|
// Generate suggestions based on search results
|
||||||
this.results.forEach((dataset) => {
|
this.results.forEach((dataset) => {
|
||||||
|
|
||||||
console.log("suggestions:foreach:", dataset.id);
|
let foundAny = false;
|
||||||
|
|
||||||
|
console.log("get suggestions:id", dataset.id);
|
||||||
|
console.log("get suggestions:title_output", dataset.title_output);
|
||||||
|
console.log("get suggestions:author", dataset.author);
|
||||||
|
console.log("get suggestions:subjects", dataset.subjects);
|
||||||
|
|
||||||
// const del = dataset.title_output?.toLowerCase();
|
// const del = dataset.title_output?.toLowerCase();
|
||||||
if (dataset.title_output.toLowerCase().includes(this.display.toLowerCase())) {
|
if (dataset.title_output.toLowerCase().includes(this.display.toLowerCase())) {
|
||||||
|
@ -102,29 +108,40 @@ export default class VsInput extends Vue {
|
||||||
// if (!suggestion["titles"].find((value) => value === title)) {
|
// if (!suggestion["titles"].find((value) => value === title)) {
|
||||||
// suggestion.titles.push(title);
|
// suggestion.titles.push(title);
|
||||||
// }
|
// }
|
||||||
|
// Check if there is already a suggestion with this title and type
|
||||||
const hasTitleSuggestion = suggestions.some((suggestion) => suggestion.value === title && suggestion.type == SearchType.Title);
|
const hasTitleSuggestion = suggestions.some((suggestion) => suggestion.value === title && suggestion.type == SearchType.Title);
|
||||||
if (!hasTitleSuggestion) {
|
if (!hasTitleSuggestion) {
|
||||||
|
// If there is no such suggestion, create a new one and add it to the suggestions array
|
||||||
const suggestion = new Suggestion(title, SearchType.Title);
|
const suggestion = new Suggestion(title, SearchType.Title);
|
||||||
suggestions.push(suggestion);
|
suggestions.push(suggestion);
|
||||||
|
foundAny = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.find(dataset.author, this.display.toLowerCase()) !== "") {
|
||||||
|
const author = this.find(dataset.author, this.display.toLowerCase());
|
||||||
|
// Check if there is already a suggestion with this author and type
|
||||||
|
const hasAuthorSuggestion = suggestions.some((suggestion) => suggestion.value === author && suggestion.type == SearchType.Author);
|
||||||
|
if (!hasAuthorSuggestion) {
|
||||||
|
const suggestion = new Suggestion(author, SearchType.Author);
|
||||||
|
suggestions.push(suggestion);
|
||||||
|
foundAny = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.find(dataset.subjects, this.display.toLowerCase()) != "") {
|
||||||
|
const subject = this.find(dataset.subjects, this.display.toLowerCase());
|
||||||
|
const hasSubjectSuggestion = suggestions.some((suggestion) => suggestion.value === subject && suggestion.type == SearchType.Subject);
|
||||||
|
if (!hasSubjectSuggestion) {
|
||||||
|
const suggestion = new Suggestion(subject, SearchType.Subject);
|
||||||
|
suggestions.push(suggestion);
|
||||||
|
foundAny = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (this.find(dataset.author, this.display.toLowerCase()) !== "") {
|
|
||||||
// const author = this.find(dataset.author, this.display.toLowerCase());
|
|
||||||
|
|
||||||
// const hasAuthorSuggestion = suggestions.some((suggestion) => suggestion.value === author && suggestion.type == SearchType.Author);
|
// if (!foundAny) {
|
||||||
// if (!hasAuthorSuggestion) {
|
// const suggestion = new Suggestion(dataset.title_output, SearchType.Fuzzy);
|
||||||
// const suggestion = new Suggestion(author, SearchType.Author);
|
// suggestions.push(suggestion);
|
||||||
// suggestions.push(suggestion);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (this.find(dataset.subject, this.display.toLowerCase()) != "") {
|
|
||||||
// const subject = this.find(dataset.subject, this.display.toLowerCase());
|
|
||||||
// const hasSubjectSuggestion = suggestions.some((suggestion) => suggestion.value === subject && suggestion.type == SearchType.Subject);
|
|
||||||
// if (!hasSubjectSuggestion) {
|
|
||||||
// const suggestion = new Suggestion(subject, SearchType.Subject);
|
|
||||||
// suggestions.push(suggestion);
|
|
||||||
// }
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return suggestions;
|
return suggestions;
|
||||||
|
@ -151,6 +168,7 @@ export default class VsInput extends Vue {
|
||||||
return this.display;
|
return this.display;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handler for search input change
|
||||||
searchChanged(): void {
|
searchChanged(): void {
|
||||||
console.log("Search changed!");
|
console.log("Search changed!");
|
||||||
this.selectedIndex = -1;
|
this.selectedIndex = -1;
|
||||||
|
@ -164,6 +182,7 @@ export default class VsInput extends Vue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform the search request
|
||||||
private resourceSearch() {
|
private resourceSearch() {
|
||||||
if (!this.display) {
|
if (!this.display) {
|
||||||
this.results = [];
|
this.results = [];
|
||||||
|
@ -174,6 +193,7 @@ export default class VsInput extends Vue {
|
||||||
this.request();
|
this.request();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make the API request to search for datasets
|
||||||
private request(): void {
|
private request(): void {
|
||||||
console.log("request()");
|
console.log("request()");
|
||||||
// DatasetService.searchTerm(this.display, this.solr.core, this.solr.host).subscribe({
|
// DatasetService.searchTerm(this.display, this.solr.core, this.solr.host).subscribe({
|
||||||
|
@ -184,6 +204,7 @@ export default class VsInput extends Vue {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle the search results
|
||||||
private dataHandler(datasets: Dataset[]): void {
|
private dataHandler(datasets: Dataset[]): void {
|
||||||
this.results = datasets;
|
this.results = datasets;
|
||||||
// console.log(datasets);
|
// console.log(datasets);
|
||||||
|
@ -192,6 +213,7 @@ export default class VsInput extends Vue {
|
||||||
// this.loading = false;
|
// this.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle errors from the search request
|
||||||
private errorHandler(err: string): void {
|
private errorHandler(err: string): void {
|
||||||
this.error = err;
|
this.error = err;
|
||||||
// this.loading = false;
|
// this.loading = false;
|
||||||
|
@ -206,6 +228,7 @@ export default class VsInput extends Vue {
|
||||||
return key === this.selectedIndex;
|
return key === this.selectedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle arrow down key press to navigate suggestions
|
||||||
onArrowDown(ev: Event): void {
|
onArrowDown(ev: Event): void {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
if (this.selectedIndex === -1) {
|
if (this.selectedIndex === -1) {
|
||||||
|
@ -216,6 +239,7 @@ export default class VsInput extends Vue {
|
||||||
this.fixScrolling();
|
this.fixScrolling();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scroll the selected suggestion into view
|
||||||
private fixScrolling() {
|
private fixScrolling() {
|
||||||
const currentElement = this.itemRefs[this.selectedIndex];
|
const currentElement = this.itemRefs[this.selectedIndex];
|
||||||
currentElement.scrollIntoView({
|
currentElement.scrollIntoView({
|
||||||
|
@ -225,6 +249,7 @@ export default class VsInput extends Vue {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle arrow up key press to navigate suggestions
|
||||||
onArrowUp(ev: Event): void {
|
onArrowUp(ev: Event): void {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
if (this.selectedIndex === -1) {
|
if (this.selectedIndex === -1) {
|
||||||
|
@ -235,6 +260,7 @@ export default class VsInput extends Vue {
|
||||||
this.fixScrolling();
|
this.fixScrolling();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle enter key press to select a suggestion
|
||||||
onEnter(): void {
|
onEnter(): void {
|
||||||
if (this.selectedIndex === -1) {
|
if (this.selectedIndex === -1) {
|
||||||
// this.$emit("nothingSelected", this.display);
|
// this.$emit("nothingSelected", this.display);
|
||||||
|
@ -260,6 +286,7 @@ export default class VsInput extends Vue {
|
||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find a search term in an array
|
||||||
private find(myarray: Array<string>, searchterm: string): string {
|
private find(myarray: Array<string>, searchterm: string): string {
|
||||||
for (let i = 0, len = myarray.length; i < len; i += 1) {
|
for (let i = 0, len = myarray.length; i < len; i += 1) {
|
||||||
if (typeof myarray[i] === "string" && myarray[i].toLowerCase().indexOf(searchterm) !== -1) {
|
if (typeof myarray[i] === "string" && myarray[i].toLowerCase().indexOf(searchterm) !== -1) {
|
||||||
|
|
|
@ -1,27 +1,63 @@
|
||||||
// import moment from "moment";
|
// import moment from "moment";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
// // SOLR Dataset original
|
||||||
|
// export interface Dataset {
|
||||||
|
// abstract_additional: Array<string>;// OpenSearch: abstract: Array<string>
|
||||||
|
// abstract_output: string;// -----
|
||||||
|
// author: Array<string>;// EQUAL
|
||||||
|
// author_sort: Array<string>;// -----
|
||||||
|
// belongs_to_bibliography: boolean;// EQUAL
|
||||||
|
// creating_corporation: string;// EQUAL
|
||||||
|
// doctype: string;// EQUAL
|
||||||
|
// geo_location: string;// EQUAL
|
||||||
|
// id: number;// EQUAL
|
||||||
|
// identifier: Identifier;// OpenSearch: identifier: Array<string>
|
||||||
|
// language: string;// EQUAL
|
||||||
|
// licence: string;// EQUAL
|
||||||
|
// publisher_name: string;// EQUAL
|
||||||
|
// server_date_published: Array<number>;// OpenSearch not array!
|
||||||
|
// subject: Array<string>;// OpenSearch: subjectS
|
||||||
|
// title_output: string;// EQUAL
|
||||||
|
// year: number;// EQUAL
|
||||||
|
// year_inverted: number;// EQUAL
|
||||||
|
// }
|
||||||
|
|
||||||
|
// OpenSearch Dataset
|
||||||
export interface Dataset {
|
export interface Dataset {
|
||||||
abstract_additional: Array<string>;
|
abstract: Array<string>;// OpenSearch: abstract: Array<string>
|
||||||
abstract_output: string;
|
// abstract_output: string;// ----- NOT in OpenSearch
|
||||||
author: Array<string>;
|
author: Array<string>;// EQUAL
|
||||||
author_sort: Array<string>;
|
// author_sort: Array<string>;// ----- NOT in OpenSearch
|
||||||
belongs_to_bibliography: boolean;
|
belongs_to_bibliography: boolean;// EQUAL
|
||||||
creating_corporation: string;
|
creating_corporation: string;// EQUAL
|
||||||
doctype: string;
|
doctype: string;// EQUAL
|
||||||
geo_location: string;
|
geo_location: string;// EQUAL
|
||||||
id: number;
|
id: number;// EQUAL
|
||||||
identifier: Identifier;
|
// identifier: Identifier;// OpenSearch: identifier: Array<string>
|
||||||
language: string;
|
identifier: Array<string>// DIFF DATATYPE
|
||||||
licence: string;
|
language: string;// EQUAL
|
||||||
publisher_name: string;
|
licence: string;// EQUAL
|
||||||
server_date_published: Array<number>;
|
publisher_name: string;// EQUAL
|
||||||
subject: Array<string>;
|
// server_date_published: Array<number>;// OpenSearch string!
|
||||||
title_output: string;
|
server_date_published: string;// DIFF DATATYPE
|
||||||
year: number;
|
// subject: Array<string>;// OpenSearch: subjectS
|
||||||
year_inverted: number;
|
subjects: Array<string>;// DIFF DATATYPE
|
||||||
|
title_output: string;// EQUAL
|
||||||
|
year: number;// EQUAL
|
||||||
|
year_inverted: number;// EQUAL
|
||||||
|
|
||||||
|
title: string // Unique in OpenSearch
|
||||||
|
title_additional: Array<string> // Unique in OpenSearch
|
||||||
|
bbox_xmin: string // Unique in OpenSearch
|
||||||
|
bbox_xmax: string // Unique in OpenSearch
|
||||||
|
bbox_ymin: string // Unique in OpenSearch
|
||||||
|
bbox_ymax: string // Unique in OpenSearch
|
||||||
|
reference: Array<string> // Unique in OpenSearch
|
||||||
|
abstract_additional: Array<string>;// Unique in OpenSearch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class Suggestion {
|
export class Suggestion {
|
||||||
constructor(
|
constructor(
|
||||||
public value: string,
|
public value: string,
|
||||||
|
@ -34,39 +70,10 @@ export class Suggestion {
|
||||||
export enum SearchType {
|
export enum SearchType {
|
||||||
Title = "title",
|
Title = "title",
|
||||||
Author = "author",
|
Author = "author",
|
||||||
Subject = "subject",
|
Subject = "subject"
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DbDataset {
|
export class DbDataset {
|
||||||
// public id!: number;
|
|
||||||
// public url!: string;
|
|
||||||
// public contributing_corporation!: string;
|
|
||||||
// public creating_corporation!: string;
|
|
||||||
// public publisher_name!: string;
|
|
||||||
// public embargo_date!: string;
|
|
||||||
// public publish_id!: number;
|
|
||||||
// public project_id!: number;
|
|
||||||
// public type!: string;
|
|
||||||
// public language!: string;
|
|
||||||
// public server_state!: string;
|
|
||||||
// public belongs_to_bibliography!: boolean;
|
|
||||||
// public created_at!: string;
|
|
||||||
// public server_date_modified!: string;
|
|
||||||
// public server_date_published!: string;
|
|
||||||
// public account_id!: number;
|
|
||||||
// public editor_id!: number;
|
|
||||||
// public reviewer_id!: number;
|
|
||||||
// public preferred_reviewer!: number;
|
|
||||||
// public preferred_reviewer_email!: string;
|
|
||||||
// public reject_editor_note!: string;
|
|
||||||
// public reject_reviewer_note!: string;
|
|
||||||
// public reviewer_note_visible!: string;
|
|
||||||
// public titles!: Array<Title>;
|
|
||||||
// public abstracts!: Array<Abstract>;
|
|
||||||
// public authors!: Array<Author>;
|
|
||||||
// public contributors!: Array<Author>;
|
|
||||||
// public user!: Person;
|
|
||||||
// public subjects!: Array<Subject>;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public id: string,
|
public id: string,
|
||||||
|
|
|
@ -105,13 +105,29 @@ export interface Hit {
|
||||||
_id: string;
|
_id: string;
|
||||||
_score: number;
|
_score: number;
|
||||||
_source: Dataset;
|
_source: Dataset;
|
||||||
|
_highlight: HitHighlight; // !! This name is to avoid collision with Typescript "Highlight" class
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HitHighlight {
|
||||||
|
subjects?: Array<string>;
|
||||||
|
title?: Array<string>;
|
||||||
|
author?: Array<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Aggregations {
|
export interface Aggregations {
|
||||||
[key: string]: Aggregation;
|
subjects: Subjects;
|
||||||
|
language: Language;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Aggregation {
|
export interface Subjects {
|
||||||
|
doc_count_error_upper_bound: number;
|
||||||
|
sum_other_doc_count: number;
|
||||||
|
buckets: Array<Bucket>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Language {
|
||||||
|
doc_count_error_upper_bound: number;
|
||||||
|
sum_other_doc_count: number;
|
||||||
buckets: Array<Bucket>;
|
buckets: Array<Bucket>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,3 +135,13 @@ export interface Bucket {
|
||||||
key: string;
|
key: string;
|
||||||
doc_count: number;
|
doc_count: number;
|
||||||
}
|
}
|
||||||
|
// // Needed?
|
||||||
|
// export interface Aggregations {
|
||||||
|
// [key: string]: Aggregation;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export interface Aggregation {
|
||||||
|
// buckets: Array<Bucket>;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import api from "../api/api";
|
import api from "../api/api";
|
||||||
// import { Observable, of } from "rxjs";
|
// import { Observable, of } from "rxjs";
|
||||||
import { Observable } from "rxjs";
|
import { Observable } from "rxjs";
|
||||||
import { map } from "rxjs/operators";
|
import { tap, map } from "rxjs/operators";
|
||||||
import { Dataset, DbDataset, Suggestion } from "@/models/dataset";
|
import { Dataset, DbDataset, Suggestion } from "@/models/dataset";
|
||||||
import { OpenSearchResponse, SolrResponse } from "@/models/headers";
|
import { OpenSearchResponse, SolrResponse } from "@/models/headers";
|
||||||
import { ActiveFilterCategories } from "@/models/solr";
|
import { ActiveFilterCategories } from "@/models/solr";
|
||||||
|
@ -16,130 +16,130 @@ class DatasetService {
|
||||||
*
|
*
|
||||||
* @param {string} searchTerm - The search term to query.
|
* @param {string} searchTerm - The search term to query.
|
||||||
*/
|
*/
|
||||||
async fetchDataFromOpenSearch(searchTerm: string): Promise<void> {
|
// async fetchDataFromOpenSearch(searchTerm: string): Promise<void> {
|
||||||
// Define the OpenSearch endpoint URL
|
// // Define the OpenSearch endpoint URL
|
||||||
const url = "http://opensearch.geoinformation.dev/tethys-records/_search";
|
// const url = "http://opensearch.geoinformation.dev/tethys-records/_search";
|
||||||
|
|
||||||
// Set the headers for the POST request
|
// // Set the headers for the POST request
|
||||||
const headers = {
|
// const headers = {
|
||||||
"Content-Type": "application/json",
|
// "Content-Type": "application/json",
|
||||||
};
|
// };
|
||||||
|
|
||||||
// Construct the body of the POST request
|
// // Construct the body of the POST request
|
||||||
const body = {
|
// const body = {
|
||||||
query: {
|
// query: {
|
||||||
bool: {
|
// bool: {
|
||||||
// The `should` clause specifies that at least one of these conditions must match
|
// // The `should` clause specifies that at least one of these conditions must match
|
||||||
should: [
|
// should: [
|
||||||
{
|
// {
|
||||||
// Match the search term in the title field with fuzziness enabled and a boost of 3
|
// // Match the search term in the title field with fuzziness enabled and a boost of 3
|
||||||
match: {
|
// match: {
|
||||||
title: {
|
// title: {
|
||||||
query: searchTerm,
|
// query: searchTerm,
|
||||||
fuzziness: "AUTO", // Enable fuzzy search
|
// fuzziness: "AUTO", // Enable fuzzy search
|
||||||
boost: 3 // Boosting the relevance of title matches
|
// boost: 3 // Boosting the relevance of title matches
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
// Match the search term in the author field with fuzziness enabled and a boost of 2
|
// // Match the search term in the author field with fuzziness enabled and a boost of 2
|
||||||
match: {
|
// match: {
|
||||||
author: {
|
// author: {
|
||||||
query: searchTerm,
|
// query: searchTerm,
|
||||||
fuzziness: "AUTO", // Enable fuzzy search
|
// fuzziness: "AUTO", // Enable fuzzy search
|
||||||
boost: 2 // Boosting the relevance of author matches
|
// boost: 2 // Boosting the relevance of author matches
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
// Match the search term in the subject field with fuzziness enabled and a boost of 1
|
// // Match the search term in the subject field with fuzziness enabled and a boost of 1
|
||||||
match: {
|
// match: {
|
||||||
subject: {
|
// subject: {
|
||||||
query: searchTerm,
|
// query: searchTerm,
|
||||||
fuzziness: "AUTO", // Enable fuzzy search
|
// fuzziness: "AUTO", // Enable fuzzy search
|
||||||
boost: 1 // Boosting the relevance of subject matches
|
// boost: 1 // Boosting the relevance of subject matches
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
// Match the search term in the title field with a wildcard
|
// // Match the search term in the title field with a wildcard
|
||||||
wildcard: {
|
// wildcard: {
|
||||||
title: {
|
// title: {
|
||||||
value: `${searchTerm}*`, // Wildcard search for terms starting with searchTerm
|
// value: `${searchTerm}*`, // Wildcard search for terms starting with searchTerm
|
||||||
boost: 3 // Boosting the relevance of title matches
|
// boost: 3 // Boosting the relevance of title matches
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
// Match the search term in the author field with a wildcard
|
// // Match the search term in the author field with a wildcard
|
||||||
wildcard: {
|
// wildcard: {
|
||||||
author: {
|
// author: {
|
||||||
value: `${searchTerm}*`, // Wildcard search for terms starting with searchTerm
|
// value: `${searchTerm}*`, // Wildcard search for terms starting with searchTerm
|
||||||
boost: 2 // Boosting the relevance of author matches
|
// boost: 2 // Boosting the relevance of author matches
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
// Match the search term in the subject field with a wildcard
|
// // Match the search term in the subject field with a wildcard
|
||||||
wildcard: {
|
// wildcard: {
|
||||||
subject: {
|
// subject: {
|
||||||
value: `${searchTerm}*`, // Wildcard search for terms starting with searchTerm
|
// value: `${searchTerm}*`, // Wildcard search for terms starting with searchTerm
|
||||||
boost: 1 // Boosting the relevance of subject matches
|
// boost: 1 // Boosting the relevance of subject matches
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
],
|
// ],
|
||||||
// Ensure that at least one of the `should` clauses must match
|
// // Ensure that at least one of the `should` clauses must match
|
||||||
minimum_should_match: 1
|
// minimum_should_match: 1
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
// Limit the number of search results to 10
|
// // Limit the number of search results to 10
|
||||||
size: 10,
|
// size: 10,
|
||||||
// Start from the first result (pagination)
|
// // Start from the first result (pagination)
|
||||||
from: 0,
|
// from: 0,
|
||||||
// Sort the results by the `server_date_published` field in descending order
|
// // Sort the results by the `server_date_published` field in descending order
|
||||||
sort: [
|
// sort: [
|
||||||
{ server_date_published: { order: "desc" } }
|
// { server_date_published: { order: "desc" } }
|
||||||
],
|
// ],
|
||||||
// Aggregations to provide facets for the `language` and `subject` fields
|
// // Aggregations to provide facets for the `language` and `subject` fields
|
||||||
aggs: {
|
// aggs: {
|
||||||
language: {
|
// language: {
|
||||||
terms: {
|
// terms: {
|
||||||
field: "language.keyword" // Aggregate by the exact values of the `language` field
|
// field: "language.keyword" // Aggregate by the exact values of the `language` field
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
subject: {
|
// subject: {
|
||||||
terms: {
|
// terms: {
|
||||||
field: "subjects.keyword", // Aggregate by the exact values of the `subjects` field
|
// field: "subjects.keyword", // Aggregate by the exact values of the `subjects` field
|
||||||
size: 10 // Limit the number of aggregation buckets to 10
|
// size: 10 // Limit the number of aggregation buckets to 10
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
try {
|
// try {
|
||||||
// Send the POST request to the OpenSearch endpoint
|
// // Send the POST request to the OpenSearch endpoint
|
||||||
const response = await fetch(url, {
|
// const response = await fetch(url, {
|
||||||
method: "POST",
|
// method: "POST",
|
||||||
headers: headers,
|
// headers: headers,
|
||||||
body: JSON.stringify(body),
|
// body: JSON.stringify(body),
|
||||||
});
|
// });
|
||||||
|
|
||||||
// Check if the response is not successful
|
// // Check if the response is not successful
|
||||||
if (!response.ok) {
|
// if (!response.ok) {
|
||||||
throw new Error(`Failed to fetch data from ${url}, status: ${response.status}`);
|
// throw new Error(`Failed to fetch data from ${url}, status: ${response.status}`);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Parse the response JSON
|
// // Parse the response JSON
|
||||||
const data = await response.json();
|
// const data = await response.json();
|
||||||
// Log the data from OpenSearch
|
// // Log the data from OpenSearch
|
||||||
console.log("Data from OpenSearch:", data);
|
// console.log("Data from OpenSearch:", data);
|
||||||
console.log("Hits:", data.hits.total.value);
|
// console.log("Hits:", data.hits.total.value);
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
// Log any errors that occur during the fetch process
|
// // Log any errors that occur during the fetch process
|
||||||
console.error("Error fetching data:", error);
|
// console.error("Error fetching data:", error);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/* https://tethys.at/solr/rdr_data/select?&0=fl%3Did%2Clicence%2Cserver_date_published%2Cabstract_output%2Cidentifier%2Ctitle_output%2Ctitle_additional%2Cauthor%2Csubject%2Cdoctype&q=%2A
|
/* https://tethys.at/solr/rdr_data/select?&0=fl%3Did%2Clicence%2Cserver_date_published%2Cabstract_output%2Cidentifier%2Ctitle_output%2Ctitle_additional%2Cauthor%2Csubject%2Cdoctype&q=%2A
|
||||||
&q.op=or&defType=edismax&qf=title%5E3%20author%5E2%20subject%5E1&indent=on&wt=json&rows=10&start=0&sort=server_date_published%20desc&facet=on&json.facet.language=%7B%20type%3A%20%22
|
&q.op=or&defType=edismax&qf=title%5E3%20author%5E2%20subject%5E1&indent=on&wt=json&rows=10&start=0&sort=server_date_published%20desc&facet=on&json.facet.language=%7B%20type%3A%20%22
|
||||||
|
@ -156,25 +156,53 @@ class DatasetService {
|
||||||
should: [
|
should: [
|
||||||
{ match: { title: { query: term, fuzziness: "AUTO", boost: 3 } } },
|
{ match: { title: { query: term, fuzziness: "AUTO", boost: 3 } } },
|
||||||
{ match: { author: { query: term, fuzziness: "AUTO", boost: 2 } } },
|
{ match: { author: { query: term, fuzziness: "AUTO", boost: 2 } } },
|
||||||
{ match: { subject: { query: term, fuzziness: "AUTO", boost: 1 } } },
|
{ match: { subjects: { query: term, fuzziness: "AUTO", boost: 1 } } }, // In SOLR is "subject"!
|
||||||
{ wildcard: { title: { value: `${term}*`, boost: 3 } } },
|
{ wildcard: { title: { value: `${term}*`, boost: 3 } } },
|
||||||
{ wildcard: { author: { value: `${term}*`, boost: 2 } } },
|
{ wildcard: { author: { value: `${term}*`, boost: 2 } } },
|
||||||
{ wildcard: { subject: { value: `${term}*`, boost: 1 } } }
|
{ wildcard: { subjects: { value: `${term}*`, boost: 1 } } } // In SOLR is "subject"!
|
||||||
],
|
],
|
||||||
minimum_should_match: 1
|
minimum_should_match: 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
size: 10,
|
size: 10,
|
||||||
from: 0,
|
from: 0,
|
||||||
sort: [{ server_date_published: { order: "desc" } }],
|
// sort: [{ server_date_published: { order: "desc" } }],
|
||||||
|
sort: [{ _score: { order: "desc" } }], // Sort by _score in descending order
|
||||||
|
track_scores: true, // This ensures "_score" is included even when sorting by other criteria. Otherwise the relevance score is not calculated
|
||||||
aggs: {
|
aggs: {
|
||||||
language: { terms: { field: "language.keyword" } },
|
language: { terms: { field: "language.keyword" } },
|
||||||
subject: { terms: { field: "subjects.keyword", size: 10 } }
|
subjects: { terms: { field: "subjects.keyword", size: 10 } } // In SOLR is "subject"!
|
||||||
|
},
|
||||||
|
highlight: {
|
||||||
|
fields: {
|
||||||
|
title: {},
|
||||||
|
author: {},
|
||||||
|
subjects: {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Make API call to OpenSearch and return the result
|
||||||
|
/**
|
||||||
|
* When a POST request is made to the OpenSearch server using the api.post<OpenSearchResponse> method, the response received from OpenSearch is an object that includes various details about the search results.
|
||||||
|
* One of the key properties of this response object is _source, which is an array of documents (datasets) that match the search criteria.
|
||||||
|
* It is used the pipe method to chain RxJS operators to the Observable returned by api.get. The map operator is used to transform the emitted items of the Observable.
|
||||||
|
*/
|
||||||
return api.post<OpenSearchResponse>(this.openSearchUrl, body).pipe(
|
return api.post<OpenSearchResponse>(this.openSearchUrl, body).pipe(
|
||||||
|
// tap(response => console.log("OpenSearchResponse:", response)), // Log the complete response
|
||||||
|
// tap(response => console.log("Aggre:", response.aggregations?.subjects.buckets[0])), // log the first subject of the array of subjects returned
|
||||||
|
// tap(response => console.log("Hits:", response.hits)), // log the first subject of the array of subjects returned
|
||||||
|
|
||||||
map(response => response.hits.hits.map(hit => hit._source))
|
map(response => response.hits.hits.map(hit => hit._source))
|
||||||
|
|
||||||
|
// map(response => response.hits.hits.map(hit => {
|
||||||
|
// const source = hit._source;
|
||||||
|
// const highlights = hit._highlight || {};
|
||||||
|
// return {
|
||||||
|
// ...source,
|
||||||
|
// highlights
|
||||||
|
// };
|
||||||
|
// }))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user