feat(vfs): fix VFS visibility by removing broken filtering
- Remove includeVFS parameter and broken isVFS filtering logic - Add excludeVFS parameter for optional VFS entity filtering - VFS entities now part of knowledge graph by default - Enable O(1) graph adjacency optimizations for VFS operations - Update all VFS projections and PathResolver - Add comprehensive VFS visibility documentation This fixes the bug where VFS operations returned empty results due to operator object mismatch in storage adapters. VFS relationships now use proper graph traversal without metadata filtering. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
5c3d2e9b67
commit
8393d01209
9 changed files with 134 additions and 85 deletions
|
|
@ -484,4 +484,81 @@ async function getDocumentsByDate(page: number, pageSize: number = 20) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## VFS (Virtual File System) Visibility (v4.7.0+)
|
||||||
|
|
||||||
|
### Default Behavior
|
||||||
|
|
||||||
|
**VFS entities are now part of the knowledge graph** and included in query results by default:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Default: Searches ALL entities including VFS files
|
||||||
|
await brain.find({ query: 'authentication setup' })
|
||||||
|
// Returns: concepts, papers, AND markdown documentation files
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why this change?** VFS files (imported markdown, PDFs, etc.) ARE knowledge entities. When you import documentation or papers into Brainy, you want to search them!
|
||||||
|
|
||||||
|
### Excluding VFS Entities
|
||||||
|
|
||||||
|
If you need to exclude VFS entities from specific queries, use the `excludeVFS` parameter:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Exclude VFS files from results
|
||||||
|
await brain.find({
|
||||||
|
query: 'machine learning',
|
||||||
|
excludeVFS: true // Only return non-file entities
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**Alternative**: Use explicit where clause for more control:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Explicit filtering (same as excludeVFS: true)
|
||||||
|
await brain.find({
|
||||||
|
query: 'machine learning',
|
||||||
|
where: { vfsType: { exists: false } }
|
||||||
|
})
|
||||||
|
|
||||||
|
// Or only search VFS files
|
||||||
|
await brain.find({
|
||||||
|
query: 'setup instructions',
|
||||||
|
where: { vfsType: 'file' } // Only files
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
**VFS filtering is production-scale:**
|
||||||
|
- Uses MetadataIndex (O(1) for exists checks)
|
||||||
|
- No performance penalty - same speed as any metadata filter
|
||||||
|
- Works seamlessly with vector + metadata + graph queries
|
||||||
|
|
||||||
|
### Migration from v4.6.x
|
||||||
|
|
||||||
|
**BREAKING CHANGE** (v4.7.0): The `includeVFS` parameter has been removed:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ❌ Old (v4.6.x and earlier)
|
||||||
|
await brain.find({
|
||||||
|
query: 'docs',
|
||||||
|
includeVFS: true // No longer needed!
|
||||||
|
})
|
||||||
|
|
||||||
|
// ✅ New (v4.7.0+)
|
||||||
|
await brain.find({
|
||||||
|
query: 'docs' // VFS included by default
|
||||||
|
})
|
||||||
|
|
||||||
|
// ✅ To exclude VFS (if needed)
|
||||||
|
await brain.find({
|
||||||
|
query: 'concepts',
|
||||||
|
excludeVFS: true
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why removed?** The old `includeVFS` parameter was:
|
||||||
|
1. Broken (metadata filter incompatibility with storage adapters)
|
||||||
|
2. Confusing (double-negative logic)
|
||||||
|
3. Wrong default (VFS should be searchable)
|
||||||
|
|
||||||
This system represents the most advanced query intelligence available in any database, combining the speed of specialized indices with the intelligence of natural language understanding and the power of graph relationships.
|
This system represents the most advanced query intelligence available in any database, combining the speed of specialized indices with the intelligence of natural language understanding and the power of graph relationships.
|
||||||
|
|
@ -1022,13 +1022,8 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
||||||
filter.service = params.service
|
filter.service = params.service
|
||||||
}
|
}
|
||||||
|
|
||||||
// v4.5.1: Exclude VFS relationships by default (same pattern as brain.find())
|
// v4.7.0: VFS relationships are no longer filtered
|
||||||
// VFS relationships have metadata.isVFS = true
|
// VFS is part of the knowledge graph - users can filter explicitly if needed
|
||||||
// Only include VFS relationships if explicitly requested
|
|
||||||
if (params.includeVFS !== true) {
|
|
||||||
filter.metadata = filter.metadata || {}
|
|
||||||
filter.metadata.isVFS = { notEquals: true }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch from storage with pagination at storage layer (efficient!)
|
// Fetch from storage with pagination at storage layer (efficient!)
|
||||||
const result = await this.storage.getVerbs({
|
const result = await this.storage.getVerbs({
|
||||||
|
|
@ -1207,18 +1202,23 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
||||||
* // Returns only knowledge entities, VFS files excluded
|
* // Returns only knowledge entities, VFS files excluded
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Include VFS entities when needed
|
* // v4.7.0: VFS entities included by default
|
||||||
* const everything = await brainy.find({
|
* const everything = await brainy.find({
|
||||||
* query: 'documentation',
|
* query: 'documentation'
|
||||||
* includeVFS: true // Opt-in to include VFS files
|
|
||||||
* })
|
* })
|
||||||
* // Returns both knowledge entities AND VFS files
|
* // Returns both knowledge entities AND VFS files
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Search only VFS files
|
* // Search only VFS files
|
||||||
* const files = await brainy.find({
|
* const files = await brainy.find({
|
||||||
* where: { vfsType: 'file', extension: '.md' },
|
* where: { vfsType: 'file', extension: '.md' }
|
||||||
* includeVFS: true // Required to find VFS entities
|
* })
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* // Exclude VFS entities (if needed)
|
||||||
|
* const concepts = await brainy.find({
|
||||||
|
* query: 'machine learning',
|
||||||
|
* excludeVFS: true // v4.7.0: Exclude VFS files
|
||||||
* })
|
* })
|
||||||
*/
|
*/
|
||||||
async find(query: string | FindParams<T>): Promise<Result<T>[]> {
|
async find(query: string | FindParams<T>): Promise<Result<T>[]> {
|
||||||
|
|
@ -1274,11 +1274,10 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
||||||
if (params.where) Object.assign(filter, params.where)
|
if (params.where) Object.assign(filter, params.where)
|
||||||
if (params.service) filter.service = params.service
|
if (params.service) filter.service = params.service
|
||||||
|
|
||||||
// v4.3.3: Exclude VFS entities by default (Option 3C architecture)
|
// v4.7.0: excludeVFS helper for cleaner UX
|
||||||
// Only include VFS if explicitly requested via includeVFS: true
|
// Use vfsType field (more semantic than isVFS)
|
||||||
// BUT: Don't add automatic exclusion if user explicitly queries isVFS in where clause
|
if (params.excludeVFS === true) {
|
||||||
if (params.includeVFS !== true && !params.where?.hasOwnProperty('isVFS')) {
|
filter.vfsType = { exists: false }
|
||||||
filter.isVFS = { notEquals: true }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.type) {
|
if (params.type) {
|
||||||
|
|
@ -1330,13 +1329,13 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
||||||
const limit = params.limit || 20
|
const limit = params.limit || 20
|
||||||
const offset = params.offset || 0
|
const offset = params.offset || 0
|
||||||
|
|
||||||
// v4.3.3: Apply VFS filtering even for empty queries
|
// v4.7.0: excludeVFS helper
|
||||||
let filter: any = {}
|
let filter: any = {}
|
||||||
if (params.includeVFS !== true) {
|
if (params.excludeVFS === true) {
|
||||||
filter.isVFS = { notEquals: true }
|
filter.vfsType = { exists: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use metadata index if we need to filter VFS
|
// Use metadata index if we need to filter
|
||||||
if (Object.keys(filter).length > 0) {
|
if (Object.keys(filter).length > 0) {
|
||||||
const filteredIds = await this.metadataIndex.getIdsForFilter(filter)
|
const filteredIds = await this.metadataIndex.getIdsForFilter(filter)
|
||||||
const pageIds = filteredIds.slice(offset, offset + limit)
|
const pageIds = filteredIds.slice(offset, offset + limit)
|
||||||
|
|
@ -1399,7 +1398,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply O(log n) metadata filtering using core MetadataIndexManager
|
// Apply O(log n) metadata filtering using core MetadataIndexManager
|
||||||
if (params.where || params.type || params.service || params.includeVFS !== true) {
|
if (params.where || params.type || params.service || params.excludeVFS) {
|
||||||
// Build filter object for metadata index
|
// Build filter object for metadata index
|
||||||
let filter: any = {}
|
let filter: any = {}
|
||||||
|
|
||||||
|
|
@ -1407,10 +1406,9 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
||||||
if (params.where) Object.assign(filter, params.where)
|
if (params.where) Object.assign(filter, params.where)
|
||||||
if (params.service) filter.service = params.service
|
if (params.service) filter.service = params.service
|
||||||
|
|
||||||
// v4.3.3: Exclude VFS entities by default (Option 3C architecture)
|
// v4.7.0: excludeVFS helper for cleaner UX
|
||||||
// BUT: Don't add automatic exclusion if user explicitly queries isVFS in where clause
|
if (params.excludeVFS === true) {
|
||||||
if (params.includeVFS !== true && !params.where?.hasOwnProperty('isVFS')) {
|
filter.vfsType = { exists: false }
|
||||||
filter.isVFS = { notEquals: true }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.type) {
|
if (params.type) {
|
||||||
|
|
@ -1704,7 +1702,7 @@ export class Brainy<T = any> implements BrainyInterface<T> {
|
||||||
type: params.type,
|
type: params.type,
|
||||||
where: params.where,
|
where: params.where,
|
||||||
service: params.service,
|
service: params.service,
|
||||||
includeVFS: params.includeVFS // v4.4.0: Pass through VFS filtering
|
excludeVFS: params.excludeVFS // v4.7.0: Pass through VFS filtering
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -347,10 +347,8 @@ export const coreCommands = {
|
||||||
searchParams.includeRelations = true
|
searchParams.includeRelations = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include VFS files (v4.4.0 - find excludes VFS by default)
|
// v4.7.0: VFS is now part of the knowledge graph (included by default)
|
||||||
if (options.includeVfs) {
|
// Users can exclude VFS with --where vfsType exists:false if needed
|
||||||
searchParams.includeVFS = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Triple Intelligence Fusion - custom weighting
|
// Triple Intelligence Fusion - custom weighting
|
||||||
if (options.fusion || options.vectorWeight || options.graphWeight || options.fieldWeight) {
|
if (options.fusion || options.vectorWeight || options.graphWeight || options.fieldWeight) {
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ export interface FindParams<T = any> {
|
||||||
mode?: SearchMode // Search strategy
|
mode?: SearchMode // Search strategy
|
||||||
explain?: boolean // Return scoring explanation
|
explain?: boolean // Return scoring explanation
|
||||||
includeRelations?: boolean // Include entity relationships
|
includeRelations?: boolean // Include entity relationships
|
||||||
includeVFS?: boolean // v4.3.3: Include VFS entities (default: false for knowledge queries)
|
excludeVFS?: boolean // v4.7.0: Exclude VFS entities from results (default: false - VFS included)
|
||||||
service?: string // Multi-tenancy filter
|
service?: string // Multi-tenancy filter
|
||||||
|
|
||||||
// Triple Intelligence Fusion
|
// Triple Intelligence Fusion
|
||||||
|
|
@ -239,7 +239,7 @@ export interface SimilarParams<T = any> {
|
||||||
type?: NounType | NounType[] // Restrict to types
|
type?: NounType | NounType[] // Restrict to types
|
||||||
where?: Partial<T> // Additional filters
|
where?: Partial<T> // Additional filters
|
||||||
service?: string // Multi-tenancy
|
service?: string // Multi-tenancy
|
||||||
includeVFS?: boolean // v4.4.0: Include VFS entities (default: false)
|
excludeVFS?: boolean // v4.7.0: Exclude VFS entities (default: false - VFS included)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -328,17 +328,6 @@ export interface GetRelationsParams {
|
||||||
* Only return relationships belonging to this service.
|
* Only return relationships belonging to this service.
|
||||||
*/
|
*/
|
||||||
service?: string
|
service?: string
|
||||||
|
|
||||||
/**
|
|
||||||
* Include VFS relationships (v4.5.1)
|
|
||||||
*
|
|
||||||
* By default, getRelations() excludes VFS relationships (since v4.4.0).
|
|
||||||
* Set this to true when you need to traverse VFS structure.
|
|
||||||
*
|
|
||||||
* @default false
|
|
||||||
* @since v4.5.1
|
|
||||||
*/
|
|
||||||
includeVFS?: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============= Batch Operations =============
|
// ============= Batch Operations =============
|
||||||
|
|
|
||||||
|
|
@ -195,12 +195,11 @@ export class PathResolver {
|
||||||
// Still need to verify it exists
|
// Still need to verify it exists
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use proper graph traversal to find children
|
// v4.7.0: Use proper graph traversal to find children
|
||||||
// Get all relationships where parentId contains other entities
|
// VFS relationships are now part of the knowledge graph
|
||||||
const relations = await this.brain.getRelations({
|
const relations = await this.brain.getRelations({
|
||||||
from: parentId,
|
from: parentId,
|
||||||
type: VerbType.Contains,
|
type: VerbType.Contains
|
||||||
includeVFS: true // v4.5.1: Required to see VFS relationships
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Find the child with matching name
|
// Find the child with matching name
|
||||||
|
|
@ -225,11 +224,11 @@ export class PathResolver {
|
||||||
* Uses proper graph relationships to traverse the tree
|
* Uses proper graph relationships to traverse the tree
|
||||||
*/
|
*/
|
||||||
async getChildren(dirId: string): Promise<VFSEntity[]> {
|
async getChildren(dirId: string): Promise<VFSEntity[]> {
|
||||||
// Production-ready: Use graph relationships (VFS creates these in mkdir/writeFile)
|
// v4.7.0: Use O(1) graph relationships (VFS creates these in mkdir/writeFile)
|
||||||
|
// VFS relationships are now part of the knowledge graph (no special filtering needed)
|
||||||
const relations = await this.brain.getRelations({
|
const relations = await this.brain.getRelations({
|
||||||
from: dirId,
|
from: dirId,
|
||||||
type: VerbType.Contains,
|
type: VerbType.Contains
|
||||||
includeVFS: true // v4.5.1: Required to see VFS relationships
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const validChildren: VFSEntity[]= []
|
const validChildren: VFSEntity[]= []
|
||||||
|
|
|
||||||
|
|
@ -167,8 +167,7 @@ export class VirtualFileSystem implements IVirtualFileSystem {
|
||||||
path: '/', // ✅ Correct field name
|
path: '/', // ✅ Correct field name
|
||||||
vfsType: 'directory' // ✅ Correct field name
|
vfsType: 'directory' // ✅ Correct field name
|
||||||
},
|
},
|
||||||
limit: 10,
|
limit: 10
|
||||||
includeVFS: true // v4.4.0: CRITICAL - Must find VFS root entity!
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (existing.length > 0) {
|
if (existing.length > 0) {
|
||||||
|
|
@ -961,9 +960,8 @@ export class VirtualFileSystem implements IVirtualFileSystem {
|
||||||
limit: options?.limit || 10,
|
limit: options?.limit || 10,
|
||||||
offset: options?.offset,
|
offset: options?.offset,
|
||||||
explain: options?.explain,
|
explain: options?.explain,
|
||||||
includeVFS: true, // v4.4.0: VFS search must include VFS entities!
|
|
||||||
where: {
|
where: {
|
||||||
vfsType: 'file' // v4.4.0: Only search VFS files, not knowledge documents
|
vfsType: 'file' // v4.7.0: Search VFS files
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1012,9 +1010,8 @@ export class VirtualFileSystem implements IVirtualFileSystem {
|
||||||
limit: options?.limit || 10,
|
limit: options?.limit || 10,
|
||||||
threshold: options?.threshold || 0.7,
|
threshold: options?.threshold || 0.7,
|
||||||
type: [NounType.File, NounType.Document, NounType.Media],
|
type: [NounType.File, NounType.Document, NounType.Media],
|
||||||
includeVFS: true, // v4.4.0: VFS similarity search must include VFS entities!
|
|
||||||
where: {
|
where: {
|
||||||
vfsType: 'file' // v4.4.0: Only find similar VFS files, not knowledge documents
|
vfsType: 'file' // v4.7.0: Find similar VFS files
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -2341,8 +2338,7 @@ export class VirtualFileSystem implements IVirtualFileSystem {
|
||||||
...query.where,
|
...query.where,
|
||||||
vfsType: 'entity'
|
vfsType: 'entity'
|
||||||
},
|
},
|
||||||
limit: query.limit || 100,
|
limit: query.limit || 100
|
||||||
includeVFS: true // v4.4.0: VFS entity search must include VFS entities!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.type) {
|
if (query.type) {
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,7 @@ export class AuthorProjection extends BaseProjectionStrategy {
|
||||||
vfsType: 'file',
|
vfsType: 'file',
|
||||||
owner: authorName
|
owner: authorName
|
||||||
},
|
},
|
||||||
limit: 1000,
|
limit: 1000
|
||||||
includeVFS: true // v4.4.0: Must include VFS entities!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by filename if subpath specified
|
// Filter by filename if subpath specified
|
||||||
|
|
@ -53,14 +52,13 @@ export class AuthorProjection extends BaseProjectionStrategy {
|
||||||
* Resolve author to entity IDs using REAL Brainy.find()
|
* Resolve author to entity IDs using REAL Brainy.find()
|
||||||
*/
|
*/
|
||||||
async resolve(brain: Brainy, vfs: VirtualFileSystem, authorName: string): Promise<string[]> {
|
async resolve(brain: Brainy, vfs: VirtualFileSystem, authorName: string): Promise<string[]> {
|
||||||
// Use REAL Brainy metadata filtering
|
// v4.7.0: VFS entities are part of the knowledge graph
|
||||||
const results = await brain.find({
|
const results = await brain.find({
|
||||||
where: {
|
where: {
|
||||||
vfsType: 'file',
|
vfsType: 'file',
|
||||||
owner: authorName
|
owner: authorName
|
||||||
},
|
},
|
||||||
limit: 1000,
|
limit: 1000
|
||||||
includeVFS: true // v4.4.0: Must include VFS entities!
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.extractIds(results)
|
return this.extractIds(results)
|
||||||
|
|
@ -75,10 +73,9 @@ export class AuthorProjection extends BaseProjectionStrategy {
|
||||||
const results = await brain.find({
|
const results = await brain.find({
|
||||||
where: {
|
where: {
|
||||||
vfsType: 'file',
|
vfsType: 'file',
|
||||||
owner: { $exists: true }
|
owner: { exists: true }
|
||||||
},
|
},
|
||||||
limit,
|
limit
|
||||||
includeVFS: true // v4.4.0: Must include VFS entities!
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return results.map(r => r.entity as VFSEntity)
|
return results.map(r => r.entity as VFSEntity)
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,9 @@ export class TagProjection extends BaseProjectionStrategy {
|
||||||
const query: FindParams = {
|
const query: FindParams = {
|
||||||
where: {
|
where: {
|
||||||
vfsType: 'file',
|
vfsType: 'file',
|
||||||
tags: { contains: tagName } // BFO operator for array contains
|
tags: { contains: tagName } // contains operator for array search
|
||||||
},
|
},
|
||||||
limit: 1000,
|
limit: 1000
|
||||||
includeVFS: true // v4.4.0: Must include VFS entities!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by filename if subpath specified
|
// Filter by filename if subpath specified
|
||||||
|
|
@ -53,14 +52,13 @@ export class TagProjection extends BaseProjectionStrategy {
|
||||||
* Resolve tag to entity IDs using REAL Brainy.find()
|
* Resolve tag to entity IDs using REAL Brainy.find()
|
||||||
*/
|
*/
|
||||||
async resolve(brain: Brainy, vfs: VirtualFileSystem, tagName: string): Promise<string[]> {
|
async resolve(brain: Brainy, vfs: VirtualFileSystem, tagName: string): Promise<string[]> {
|
||||||
// Use REAL Brainy metadata filtering
|
// v4.7.0: VFS entities are part of the knowledge graph
|
||||||
const results = await brain.find({
|
const results = await brain.find({
|
||||||
where: {
|
where: {
|
||||||
vfsType: 'file',
|
vfsType: 'file',
|
||||||
tags: { contains: tagName } // BFO operator
|
tags: { contains: tagName }
|
||||||
},
|
},
|
||||||
limit: 1000,
|
limit: 1000
|
||||||
includeVFS: true // v4.4.0: Must include VFS entities!
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.extractIds(results)
|
return this.extractIds(results)
|
||||||
|
|
@ -74,10 +72,9 @@ export class TagProjection extends BaseProjectionStrategy {
|
||||||
const results = await brain.find({
|
const results = await brain.find({
|
||||||
where: {
|
where: {
|
||||||
vfsType: 'file',
|
vfsType: 'file',
|
||||||
tags: { exists: true } // BFO operator
|
tags: { exists: true } // exists operator
|
||||||
},
|
},
|
||||||
limit,
|
limit
|
||||||
includeVFS: true // v4.4.0: Must include VFS entities!
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return results.map(r => r.entity as VFSEntity)
|
return results.map(r => r.entity as VFSEntity)
|
||||||
|
|
|
||||||
|
|
@ -69,17 +69,16 @@ export class TemporalProjection extends BaseProjectionStrategy {
|
||||||
const endOfDay = new Date(date)
|
const endOfDay = new Date(date)
|
||||||
endOfDay.setHours(23, 59, 59, 999)
|
endOfDay.setHours(23, 59, 59, 999)
|
||||||
|
|
||||||
// Use REAL Brainy metadata filtering with range operators
|
// v4.7.0: VFS entities are part of the knowledge graph
|
||||||
const results = await brain.find({
|
const results = await brain.find({
|
||||||
where: {
|
where: {
|
||||||
vfsType: 'file',
|
vfsType: 'file',
|
||||||
modified: {
|
modified: {
|
||||||
greaterEqual: startOfDay.getTime(), // BFO operator
|
greaterEqual: startOfDay.getTime(),
|
||||||
lessEqual: endOfDay.getTime() // BFO operator
|
lessEqual: endOfDay.getTime()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
limit: 1000,
|
limit: 1000
|
||||||
includeVFS: true // v4.4.0: Must include VFS entities!
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.extractIds(results)
|
return this.extractIds(results)
|
||||||
|
|
@ -94,10 +93,9 @@ export class TemporalProjection extends BaseProjectionStrategy {
|
||||||
const results = await brain.find({
|
const results = await brain.find({
|
||||||
where: {
|
where: {
|
||||||
vfsType: 'file',
|
vfsType: 'file',
|
||||||
modified: { greaterEqual: oneDayAgo } // BFO operator
|
modified: { greaterEqual: oneDayAgo }
|
||||||
},
|
},
|
||||||
limit,
|
limit
|
||||||
includeVFS: true // v4.4.0: Must include VFS entities!
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return results.map(r => r.entity as VFSEntity)
|
return results.map(r => r.entity as VFSEntity)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue