mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-24 17:10:12 +08:00
Implement UpdateDataset and UpdateMetadata in GO (#13928)
### What problem does this PR solve? Implement UpdateDataset and UpdateMetadata in GO Add cli: UPDATE CHUNK <chunk_id> OF DATASET <dataset_name> SET <update_fields> REMOVE TAGS 'tag1', 'tag2' from DATASET 'dataset_name'; SET METADATA OF DOCUMENT <doc_id> TO <meta> ### Type of change - [ ] Refactoring
This commit is contained in:
@@ -33,12 +33,8 @@ func (p *Parser) parseLoginUser() (*Command, error) {
|
||||
cmd.Params["email"] = email
|
||||
|
||||
p.nextToken()
|
||||
// Optional: WITH PASSWORD 'password'
|
||||
if p.curToken.Type == TokenWith {
|
||||
p.nextToken()
|
||||
if p.curToken.Type != TokenPassword {
|
||||
return nil, fmt.Errorf("expected PASSWORD after WITH")
|
||||
}
|
||||
// Optional: PASSWORD 'password'
|
||||
if p.curToken.Type == TokenPassword {
|
||||
p.nextToken()
|
||||
password, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
@@ -853,6 +849,17 @@ func (p *Parser) parseDeleteCommand() (*Command, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseRemoveCommand() (*Command, error) {
|
||||
p.nextToken() // consume RM
|
||||
|
||||
switch p.curToken.Type {
|
||||
case TokenTag:
|
||||
return p.parseRemoveTags()
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown REMOVE target: %s", p.curToken.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) parseDropToken() (*Command, error) {
|
||||
p.nextToken() // consume TOKEN
|
||||
|
||||
@@ -1574,6 +1581,9 @@ func (p *Parser) parseSetCommand() (*Command, error) {
|
||||
if p.curToken.Type == TokenToken {
|
||||
return p.parseSetToken()
|
||||
}
|
||||
if p.curToken.Type == TokenMetadata {
|
||||
return p.parseSetMeta()
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown SET target: %s", p.curToken.Value)
|
||||
}
|
||||
@@ -2229,7 +2239,10 @@ func (p *Parser) parseUserStatement() (*Command, error) {
|
||||
return p.parseInsertCommand()
|
||||
case TokenSearch:
|
||||
return p.parseSearchCommand()
|
||||
|
||||
case TokenUpdate:
|
||||
return p.parseUpdateCommand()
|
||||
case TokenRemove:
|
||||
return p.parseRemoveCommand()
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid user statement: %s", p.curToken.Value)
|
||||
}
|
||||
@@ -2318,3 +2331,164 @@ func (p *Parser) parseUnsetCommand() (*Command, error) {
|
||||
}
|
||||
return NewCommand("unset_token"), nil
|
||||
}
|
||||
|
||||
// parseUpdateCommand parses UPDATE CHUNK command
|
||||
// UPDATE CHUNK 'chunk_id' OF DATASET 'dataset_name' SET '{"content": "..."}'
|
||||
func (p *Parser) parseUpdateCommand() (*Command, error) {
|
||||
p.nextToken() // consume UPDATE
|
||||
|
||||
if p.curToken.Type != TokenChunk {
|
||||
return nil, fmt.Errorf("expected CHUNK after UPDATE")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Parse chunk_id
|
||||
chunkID, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected chunk_id: %w", err)
|
||||
}
|
||||
|
||||
cmd := NewCommand("update_chunk")
|
||||
cmd.Params["chunk_id"] = chunkID
|
||||
|
||||
p.nextToken()
|
||||
if p.curToken.Type != TokenOf {
|
||||
return nil, fmt.Errorf("expected OF after chunk_id")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
if p.curToken.Type != TokenDataset {
|
||||
return nil, fmt.Errorf("expected DATASET after OF")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Parse dataset_name
|
||||
datasetName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected dataset_name: %w", err)
|
||||
}
|
||||
cmd.Params["dataset_name"] = datasetName
|
||||
|
||||
p.nextToken()
|
||||
if p.curToken.Type != TokenSet {
|
||||
return nil, fmt.Errorf("expected SET after dataset_name")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Parse JSON body
|
||||
jsonBody, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected JSON body: %w", err)
|
||||
}
|
||||
cmd.Params["json_body"] = jsonBody
|
||||
|
||||
p.nextToken()
|
||||
// Semicolon is optional
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// parseSetMeta parses: SET METADATA OF DOCUMENT 'doc_id' TO '{"key": "value"}'
|
||||
func (p *Parser) parseSetMeta() (*Command, error) {
|
||||
p.nextToken() // consume METADATA
|
||||
|
||||
// Expect OF
|
||||
if p.curToken.Type != TokenOf {
|
||||
return nil, fmt.Errorf("expected OF after SET METADATA")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Expect DOCUMENT
|
||||
if p.curToken.Type != TokenDocument {
|
||||
return nil, fmt.Errorf("expected DOCUMENT after SET METADATA OF")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Parse doc_id
|
||||
docID, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected doc_id: %w", err)
|
||||
}
|
||||
cmd := NewCommand("set_meta")
|
||||
cmd.Params["doc_id"] = docID
|
||||
|
||||
p.nextToken()
|
||||
// Expect TO
|
||||
if p.curToken.Type != TokenTo {
|
||||
return nil, fmt.Errorf("expected TO after doc_id")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Parse meta JSON
|
||||
meta, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected meta JSON: %w", err)
|
||||
}
|
||||
cmd.Params["meta"] = meta
|
||||
|
||||
p.nextToken()
|
||||
// Semicolon is optional
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
// parseRemoveTags parses: REMOVE TAGS 'tag1', 'tag2' from DATASET 'dataset_name';
|
||||
func (p *Parser) parseRemoveTags() (*Command, error) {
|
||||
p.nextToken() // consume TAGS
|
||||
|
||||
// Parse first tag
|
||||
tag, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected tag: %w", err)
|
||||
}
|
||||
tags := []string{tag}
|
||||
|
||||
// Parse additional tags separated by commas
|
||||
for {
|
||||
p.nextToken()
|
||||
if p.curToken.Type == TokenComma {
|
||||
p.nextToken()
|
||||
tag, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected tag after comma: %w", err)
|
||||
}
|
||||
tags = append(tags, tag)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
cmd := NewCommand("rm_tags")
|
||||
cmd.Params["tags"] = tags
|
||||
|
||||
// Expect from
|
||||
if p.curToken.Type != TokenFrom {
|
||||
return nil, fmt.Errorf("expected FROM after tags")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Expect DATASET
|
||||
if p.curToken.Type != TokenDataset {
|
||||
return nil, fmt.Errorf("expected DATASET after FROM")
|
||||
}
|
||||
p.nextToken()
|
||||
|
||||
// Parse dataset_name
|
||||
datasetName, err := p.parseQuotedString()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("expected dataset_name: %w", err)
|
||||
}
|
||||
cmd.Params["dataset_name"] = datasetName
|
||||
|
||||
// Semicolon is optional
|
||||
if p.curToken.Type == TokenSemicolon {
|
||||
p.nextToken()
|
||||
}
|
||||
|
||||
return cmd, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user