Aller au contenu principal
Version: 3.0.0

label components

Generic label components for @midwayjs/faas, @midwayjs/web, @midwayjs/koa and @midwayjs/express multiple frameworks.

scenes to be used

Tags are an abstract server-side common systematization capability that can be used for various purposes, such as:

  • Organize and manage resources
    • Implement a taxonomy system (for content, crowd, etc.)
    • Resource management system
      • Add various color tags, object and scene tags to pictures, and filter pictures by tags
      • Video and other material tags
  • access control
    • Permissions system (admin, editor, guest)
  • status system (editing, published, etc.)

Based on the addition, deletion, modification and query provided by the tag system, as well as the addition, deletion, modification and query of entities bound to tags through tags, more advanced business logic can be easily implemented.

The labeling system is for this kind of business scenario, allowing the server to achieve more efficient and convenient business development based on labeling capabilities.

Related Information:

web support
@midwayjs/koa
@midwayjs/faas
@midwayjs/web
@midwayjs/express

how to use?

  1. Install dependencies
$ npm i @midwayjs/tags --save
  1. Introduce components in configuration
// src/configuration.ts
import { Configuration } from '@midwayjs/core';
import * as tags from '@midwayjs/tags';
@Configuration({
imports: [
//...
tags
],
})
export class MainConfiguration {}
  1. Add configuration
// src/config/config.local.ts
export default {
tags: {
clients: {
'tagGroup1': {
// Use local memory as data storage
dialectType: 'memory',
},
},
}
}
  1. Call in the code
// src/testTags.ts
import { Provide, Inject, InjectClient } from '@midwayjs/core';
import { TagServiceFactory, TagClient } from '@midwayjs/tags';
@Provide()
export class TestTagsService {
@Inject()
tags: TagServiceFactory;

// Equivalent to this.tags.get('tagGroup1')
@InjectClient(TagServiceFactory, 'tagGroup1')
tagClient: TagClient;

@ServerlessTrigger(ServerlessTriggerType. HTTP, { path: '/tags/list', method: 'get'})
async listTags() {
// You can also use this.tagClient directly
const tagClient: TagClient = this. tags. get('tagGroup1');
// add new tag
const tagInfo = await tagClient. new({
name: 'test-tag-name',
desc: 'tag desc',
});
/*
tagInfo = {
success: true,
id: 1,
}
*/
// list top 20 tags
const tags = await tagClient. list({ count: true });
/*
tags: {
list: [
{
id: 1,
name: 'test-tag-name',
desc: 'tag desc'
}
],
total: 1
}
*/
return tags;
}
}

method

Add tag new

new(tagDefine: {
// Tag name, cannot be repeated in the same group
name: string;
// label description
desc?: string;
}): Promise<{
success: boolean;
message: string;
// label id
id?: number;
}>;

Remove tags remove

Deleting a label will also delete the entity relationship bound to this label

remove(tagIdOrName: number | string): Promise<{
success: boolean;
message: string;
// label id
id?: number;
}>;

Update tag update

Fine-tune the basic information of a label

update(tagIdOrName: number | string, params: Partial< {
name: string;
desc?: string;
}>): Promise<{
success: boolean;
message: string;
// label id
id?: number;
}>;

Enumerate tags list

Search tags, support pagination

list(listOptions?: {
// Search tags, support passing in tag id and tag name
tags?: Array<number | string>;
// When searching, whether to use the intersection or union of the tags, the values are and and or
type?: MATCH_TYPE;
count?: boolean;
pageSize?: number;
page?: number;
}): Promise<{
// label list
list: {
id: number;
name: string;
desc: string;
createAt: number;
updateAt: number;
}[];
// total number of tags
total?: number;
}>;

Binding entity bind

Binding an entity means binding anything else to a label. The entity here can be a picture or a file. The id of the entity is controlled by the user

bind(bindOptions: {
// label list
tags: Array<number | string>;
// If there is no label, automatically create a label and bind it, the default is false
autoCreateTag?: boolean;
// entity id
objectId: number,
}): Promise<{
success: boolean;
message: string;
}>

Unbind entity unbind

unbind(unbindOptions: {
// Unbound multiple tags, tag id or tag name
tags: Array<number | string>,
// entity id
objectId: number,
}): Promise<{
success: boolean;
message: string;
}>

List entities by label listObjects

listObjects(listOptions?: {
// tag id or tag name
tags?: Array<string|number>;
count?: boolean;
// When searching, whether to use the intersection or union of the tags, the values are and and or
type?: MATCH_TYPE;
pageSize?: number;
page?: number;
}): Promise<{
// list of entity ids
list: number[];
// total number of entities
total?: number;
}>;

Obtain tags based on entities listObjectTags

listObjectTags(listOptions?: {
// entity id
objectId: number;
count?: boolean;
pageSize?: number;
page?: number;

}): Promise<{
list: { // label list
name: string;
desc?: string;
id: number;
createAt: number;
updateAt: number;
}[];
// total number of tags
total?: number;
}>;

configuration

Tags supports memory storage (default) and mysql database storage. The following is a configuration example:

// src/config/config.local.ts
export default {
tags: {
clients: {
'tagGroup1': {
// Use local memory as data storage
dialectType: 'memory',
},
'tagGroup2': {
// use mysql as data store
dialectType: 'mysql',
// Automatically synchronize the table structure
sync: true,
// mysql connection instance
instance: mysqlConnection. promise(),
},
},
}
}

Memory storage configuration

ConfigurationValue TypeDefault ValueConfiguration Description
dialectTypestring memory-Configured as memory, enable memory storage

Mysql storage configuration

If you want to use Mysql database as data storage, you need to pass Mysql's database connection object into the configuration of tags.

ConfigurationValue TypeDefault ValueConfiguration Description
dialectTypestring mysql-Configure to mysql, then enable Mysql storage
syncbooleanfalseAutomatically synchronize the table structure of Tags, the Tags component will create two data tables, see the data table information below for details
instance{ query: (sql: string, placeholder?: any[])}: Promise<[]>-Mysql connection example, need to provide a query method, you can check the example below
tablePrefixstring-data table prefix
tableSeparatorstring_splicing separator of data table

The following is an example of database connection using mysql2 npm package:

// src/config/config.local.ts
const mysql = require('mysql2');
export default () => {
const connection = mysql.createConnection({
host: 'db4free.net',
user: 'tag***',
password: 'tag***',
database: 'tag***',
charset: 'utf8',
});
return {
tags: {
clients: {
'tagGroup': {
dialectType: 'mysql',
sync: true,
instance: { // mysql connection instance containing query
query: (...args) => {
return connection.promise().query(...args);
}
},
},
},
}
}
}

You can also consider making the database connection in the onConfigLoad life cycle in configuration.ts, the advantage of this is that the database connection can be closed when it is closed:

// src/configuration.ts
import { Config, Configuration } from '@midwayjs/core';
import { join } from 'path';
import * as tags from '@midwayjs/tags';
import { ITagMysqlDialectOption } from '@midwayjs/tags';
const mysql = require('mysql2');

@Configuration({
imports: [
tags
],
})
export class MainConfiguration {
connection;

@Config()
tags;

async onConfigLoad(container) {
// create mysql connection
this.connection = mysql.createConnection({
host: 'db4free.net',
user: 'tag***',
password: 'tag***',
database: 'tag***',
charset: 'utf8',
});
let dialect: ITagMysqlDialectOption = {
dialectType: 'mysql',
sync: true,
instance: {
query: (...args) => {
return this.connection.promise().query(...args);
}
}
};

return {
tags: dialect
}
}

async onStop() {
// close mysql connection
this.connection.close();
}
}

Data table information

The Tags component needs two data tables to store data, namely tag and relationship. The real table names of these two tables in the database are through the table name prefix and table name separator in the configuration. Spliced with client name/group name, for example:

const clientName = 'local-test';
const { tablePrefix = 'a', tableSeparator = '_' } = tagOptions;
const tagTableName = `${tablePrefix}${tableSeparator}${clientName}${tableSeparator}tag`;
// tagTableName: a_local-test_tag
const relationshipTableName = `${tablePrefix}${tableSeparator}${clientName}${tableSeparator}relationship`
// relationshipTableName: a_local-test-relationship

When you enable the automatic table structure synchronization of sync in the configuration, if there are no these two tables, the corresponding data table will be created according to the following table structure:

tag table structure:

CREATE TABLE `tag` (
`id` BIGINT unsigned NOT NULL AUTO_INCREMENT,
`group` varchar(32) NULL,
`name` varchar(32) NULL,
`descri` varchar(128) NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
`update_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (id)
)

relationship table structure:

CREATE TABLE `relationship` (
`id` BIGINT unsigned NOT NULL AUTO_INCREMENT,
`tid` BIGINT unsigned NOT NULL,
`oid` BIGINT unsigned NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
`update_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (id)
)