mirror of https://github.com/Squidex/squidex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
7.8 KiB
222 lines
7.8 KiB
// ==========================================================================
|
|
// Squidex Headless CMS
|
|
// ==========================================================================
|
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
// All rights reserved. Licensed under the MIT license.
|
|
// ==========================================================================
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using MongoDB.Driver;
|
|
using NodaTime;
|
|
using Squidex.Domain.Apps.Core.Contents;
|
|
using Squidex.Domain.Apps.Entities.Apps;
|
|
using Squidex.Domain.Apps.Entities.Contents;
|
|
using Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations;
|
|
using Squidex.Domain.Apps.Entities.Schemas;
|
|
using Squidex.Infrastructure;
|
|
using Squidex.Infrastructure.MongoDb;
|
|
using Squidex.Infrastructure.Queries;
|
|
using Squidex.Log;
|
|
|
|
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
|
|
{
|
|
public sealed class MongoContentCollection : MongoRepositoryBase<MongoContentEntity>
|
|
{
|
|
private readonly QueryAsStream queryAsStream;
|
|
private readonly QueryById queryBdId;
|
|
private readonly QueryByIds queryByIds;
|
|
private readonly QueryByQuery queryByQuery;
|
|
private readonly QueryReferences queryReferences;
|
|
private readonly QueryReferrers queryReferrers;
|
|
private readonly QueryScheduled queryScheduled;
|
|
private readonly string name;
|
|
private readonly ReadPreference readPreference;
|
|
|
|
public MongoContentCollection(string name, IMongoDatabase database, IAppProvider appProvider, ReadPreference readPreference)
|
|
: base(database)
|
|
{
|
|
this.name = name;
|
|
|
|
queryAsStream = new QueryAsStream();
|
|
queryBdId = new QueryById();
|
|
queryByIds = new QueryByIds();
|
|
queryByQuery = new QueryByQuery(appProvider);
|
|
queryReferences = new QueryReferences(queryByIds);
|
|
queryReferrers = new QueryReferrers();
|
|
queryScheduled = new QueryScheduled();
|
|
|
|
this.readPreference = readPreference;
|
|
}
|
|
|
|
public IMongoCollection<MongoContentEntity> GetInternalCollection()
|
|
{
|
|
return Collection;
|
|
}
|
|
|
|
protected override string CollectionName()
|
|
{
|
|
return name;
|
|
}
|
|
|
|
protected override MongoCollectionSettings CollectionSettings()
|
|
{
|
|
return new MongoCollectionSettings
|
|
{
|
|
ReadPreference = readPreference
|
|
};
|
|
}
|
|
|
|
protected override Task SetupCollectionAsync(IMongoCollection<MongoContentEntity> collection,
|
|
CancellationToken ct)
|
|
{
|
|
var operations = new OperationBase[]
|
|
{
|
|
queryAsStream,
|
|
queryBdId,
|
|
queryByIds,
|
|
queryByQuery,
|
|
queryReferences,
|
|
queryReferrers,
|
|
queryScheduled
|
|
};
|
|
|
|
foreach (var operation in operations)
|
|
{
|
|
operation.Setup(collection);
|
|
}
|
|
|
|
return collection.Indexes.CreateManyAsync(operations.SelectMany(x => x.CreateIndexes()), ct);
|
|
}
|
|
|
|
public Task ResetScheduledAsync(DomainId documentId,
|
|
CancellationToken ct)
|
|
{
|
|
return Collection.UpdateOneAsync(x => x.DocumentId == documentId, Update.Unset(x => x.ScheduleJob).Unset(x => x.ScheduledAt), cancellationToken: ct);
|
|
}
|
|
|
|
public IAsyncEnumerable<IContentEntity> StreamAll(DomainId appId, HashSet<DomainId>? schemaIds,
|
|
CancellationToken ct)
|
|
{
|
|
return queryAsStream.StreamAll(appId, schemaIds, ct);
|
|
}
|
|
|
|
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, List<ISchemaEntity> schemas, Q q,
|
|
CancellationToken ct)
|
|
{
|
|
using (Profiler.TraceMethod<MongoContentRepository>())
|
|
{
|
|
if (q.Ids != null && q.Ids.Count > 0)
|
|
{
|
|
return await queryByIds.QueryAsync(app.Id, schemas, q, ct);
|
|
}
|
|
|
|
if (q.Referencing != default)
|
|
{
|
|
return await queryReferences.QueryAsync(app.Id, schemas, q, ct);
|
|
}
|
|
|
|
if (q.Reference != default)
|
|
{
|
|
return await queryByQuery.QueryAsync(app, schemas, q, ct);
|
|
}
|
|
|
|
return ResultList.CreateFrom<IContentEntity>(0);
|
|
}
|
|
}
|
|
|
|
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q,
|
|
CancellationToken ct)
|
|
{
|
|
using (Profiler.TraceMethod<MongoContentRepository>())
|
|
{
|
|
if (q.Ids != null && q.Ids.Count > 0)
|
|
{
|
|
return await queryByIds.QueryAsync(app.Id, new List<ISchemaEntity> { schema }, q, ct);
|
|
}
|
|
|
|
if (q.Referencing == default)
|
|
{
|
|
return await queryByQuery.QueryAsync(app, schema, q, ct);
|
|
}
|
|
|
|
return ResultList.CreateFrom<IContentEntity>(0);
|
|
}
|
|
}
|
|
|
|
public async Task<IContentEntity?> FindContentAsync(ISchemaEntity schema, DomainId id,
|
|
CancellationToken ct)
|
|
{
|
|
using (Profiler.TraceMethod<MongoContentRepository>())
|
|
{
|
|
return await queryBdId.QueryAsync(schema, id, ct);
|
|
}
|
|
}
|
|
|
|
public async Task QueryScheduledWithoutDataAsync(Instant now, Func<IContentEntity, Task> callback,
|
|
CancellationToken ct)
|
|
{
|
|
using (Profiler.TraceMethod<MongoContentRepository>())
|
|
{
|
|
await queryScheduled.QueryAsync(now, callback, ct);
|
|
}
|
|
}
|
|
|
|
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids,
|
|
CancellationToken ct)
|
|
{
|
|
using (Profiler.TraceMethod<MongoContentRepository>())
|
|
{
|
|
return await queryByIds.QueryIdsAsync(appId, ids, ct);
|
|
}
|
|
}
|
|
|
|
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode<ClrValue> filterNode,
|
|
CancellationToken ct)
|
|
{
|
|
using (Profiler.TraceMethod<MongoContentRepository>())
|
|
{
|
|
return await queryByQuery.QueryIdsAsync(appId, schemaId, filterNode, ct);
|
|
}
|
|
}
|
|
|
|
public async Task<bool> HasReferrersAsync(DomainId appId, DomainId contentId,
|
|
CancellationToken ct)
|
|
{
|
|
using (Profiler.TraceMethod<MongoContentRepository>())
|
|
{
|
|
return await queryReferrers.CheckExistsAsync(appId, contentId, ct);
|
|
}
|
|
}
|
|
|
|
public async Task<long> FindVersionAsync(DomainId documentId)
|
|
{
|
|
var result = await Collection.Find(x => x.DocumentId == documentId).Only(x => x.Version).FirstOrDefaultAsync();
|
|
|
|
return result?["vs"].AsInt64 ?? EtagVersion.Empty;
|
|
}
|
|
|
|
public Task UpsertVersionedAsync(DomainId documentId, long oldVersion, MongoContentEntity entity)
|
|
{
|
|
return Collection.UpsertVersionedAsync(documentId, oldVersion, entity.Version, entity);
|
|
}
|
|
|
|
public Task RemoveAsync(DomainId documentId)
|
|
{
|
|
return Collection.DeleteOneAsync(x => x.DocumentId == documentId);
|
|
}
|
|
|
|
public Task InsertManyAsync(IReadOnlyList<MongoContentEntity> entities)
|
|
{
|
|
if (entities.Count == 0)
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
return Collection.InsertManyAsync(entities, InsertUnordered);
|
|
}
|
|
}
|
|
}
|
|
|