diff --git a/.github/workflows/Delete_build_and_test_on_main.yml b/.github/workflows/Delete_build_and_test_on_main.yml
index ad724ee..4bc125d 100644
--- a/.github/workflows/Delete_build_and_test_on_main.yml
+++ b/.github/workflows/Delete_build_and_test_on_main.yml
@@ -2,7 +2,7 @@ name: Delete build main
on:
push:
- branches:
+ branches:
- master
paths:
- 'Frends.MongoDB.Delete/**'
diff --git a/.github/workflows/Index_build_and_test_on_main.yml b/.github/workflows/Index_build_and_test_on_main.yml
new file mode 100644
index 0000000..83cc8eb
--- /dev/null
+++ b/.github/workflows/Index_build_and_test_on_main.yml
@@ -0,0 +1,18 @@
+name: Index build main
+
+on:
+ push:
+ branches:
+ - master
+ paths:
+ - 'Frends.MongoDB.Index/**'
+ workflow_dispatch:
+
+jobs:
+ build:
+ uses: FrendsPlatform/FrendsTasks/.github/workflows/linux_build_main.yml@main
+ with:
+ workdir: Frends.MongoDB.Index
+ prebuild_command: docker-compose -f ./Frends.MongoDB.Index.Tests/Files/docker-compose.yml up -d
+ secrets:
+ badge_service_api_key: ${{ secrets.BADGE_SERVICE_API_KEY }}
diff --git a/.github/workflows/Index_build_and_test_on_push.yml b/.github/workflows/Index_build_and_test_on_push.yml
new file mode 100644
index 0000000..5de0e5e
--- /dev/null
+++ b/.github/workflows/Index_build_and_test_on_push.yml
@@ -0,0 +1,19 @@
+name: Index build test
+
+on:
+ push:
+ branches-ignore:
+ - master
+ paths:
+ - 'Frends.MongoDB.Index/**'
+ workflow_dispatch:
+
+jobs:
+ build:
+ uses: FrendsPlatform/FrendsTasks/.github/workflows/linux_build_test.yml@main
+ with:
+ workdir: Frends.MongoDB.Index
+ prebuild_command: docker-compose -f ./Frends.MongoDB.Index.Tests/Files/docker-compose.yml up -d
+ secrets:
+ badge_service_api_key: ${{ secrets.BADGE_SERVICE_API_KEY }}
+ test_feed_api_key: ${{ secrets.TASKS_TEST_FEED_API_KEY }}
diff --git a/.github/workflows/Index_release.yml b/.github/workflows/Index_release.yml
new file mode 100644
index 0000000..2432706
--- /dev/null
+++ b/.github/workflows/Index_release.yml
@@ -0,0 +1,12 @@
+name: Index release
+
+on:
+ workflow_dispatch:
+
+jobs:
+ build:
+ uses: FrendsPlatform/FrendsTasks/.github/workflows/release.yml@main
+ with:
+ workdir: Frends.MongoDB.Index
+ secrets:
+ feed_api_key: ${{ secrets.TASKS_FEED_API_KEY }}
\ No newline at end of file
diff --git a/.github/workflows/Insert_build_and_test_on_main.yml b/.github/workflows/Insert_build_and_test_on_main.yml
index a0b158f..5b12981 100644
--- a/.github/workflows/Insert_build_and_test_on_main.yml
+++ b/.github/workflows/Insert_build_and_test_on_main.yml
@@ -2,7 +2,7 @@ name: Insert build main
on:
push:
- branches:
+ branches:
- master
paths:
- 'Frends.MongoDB.Insert/**'
diff --git a/.github/workflows/Query_build_and_test_on_main.yml b/.github/workflows/Query_build_and_test_on_main.yml
index 15d8970..c0e8f64 100644
--- a/.github/workflows/Query_build_and_test_on_main.yml
+++ b/.github/workflows/Query_build_and_test_on_main.yml
@@ -2,7 +2,7 @@ name: Query build main
on:
push:
- branches:
+ branches:
- master
paths:
- 'Frends.MongoDB.Query/**'
diff --git a/Frends.MongoDB.Delete/CHANGELOG.md b/Frends.MongoDB.Delete/CHANGELOG.md
index bc0d207..fcf51e4 100644
--- a/Frends.MongoDB.Delete/CHANGELOG.md
+++ b/Frends.MongoDB.Delete/CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog
+## [2.0.0] - 2025-03-12
+### Added
+- Adds caching for the MongoClient connection to improve performance.
+
+### Updated
+- Updated MongoDB.Driver to version 3.2.1
+
+### Breaking changes
+- The MongoDB driver drops support for MongoDB Server v3.6 and earlier.
+- The MongoDB driver drops support for .NET Core 2.x and .NET Framework 4.6.
+- Read more about MongoDB driver 3.0 breaking changes [here](https://mongodb.github.io/mongo-csharp-driver/3.0/reference/breaking_changes/)
+
## [1.0.1] - 2023-11-22
### Fixed
- Fixed dll error when importing the Task to Frends by adding local dll reference to the project file.
diff --git a/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/Files/docker-compose.yml b/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/Files/docker-compose.yml
index cd14b47..56b9789 100644
--- a/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/Files/docker-compose.yml
+++ b/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/Files/docker-compose.yml
@@ -1,7 +1,7 @@
version: '3'
services:
mongo:
- image: mongo:3
+ image: mongo:7
environment:
- AUTH=yes
- MONGO_INITDB_ROOT_USERNAME=admin
diff --git a/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/Frends.MongoDB.Delete.Tests.csproj b/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/Frends.MongoDB.Delete.Tests.csproj
index ee26df2..262fd45 100644
--- a/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/Frends.MongoDB.Delete.Tests.csproj
+++ b/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/Frends.MongoDB.Delete.Tests.csproj
@@ -9,16 +9,15 @@
-
-
-
-
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
-
-
-
-
diff --git a/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/UnitTests.cs b/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/UnitTests.cs
index eeadac0..7d54e44 100644
--- a/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/UnitTests.cs
+++ b/Frends.MongoDB.Delete/Frends.MongoDB.Delete.Tests/UnitTests.cs
@@ -8,21 +8,23 @@ namespace Frends.MongoDB.Delete.Tests;
[TestClass]
public class UnitTests
{
- ///
- /// Run command 'docker-compose up -d' in \Frends.MongoDB.Delete.Tests\Files\
- ///
-
- private static readonly Connection _connection = new()
- {
- ConnectionString = "mongodb://admin:Salakala@localhost:27017/?authSource=admin",
- Database = "testdb",
- CollectionName = "testcoll",
- };
-
- private readonly string _doc1 = "{ \"foo\":\"bar\", \"bar\": \"foo\" }";
- private readonly string _doc2 = "{ \"foo\":\"bar\", \"bar\": \"foo\" }";
- private readonly string _doc3 = "{ \"qwe\":\"rty\", \"asd\": \"fgh\" }";
-
+ ///
+ /// Run command 'docker-compose up -d' in \Frends.MongoDB.Delete.Tests\Files\
+ ///
+
+ private static readonly Connection _connection = new()
+ {
+ ConnectionString = "mongodb://admin:Salakala@localhost:27017/?authSource=admin",
+ Database = "testdb",
+ CollectionName = "testcoll",
+ };
+
+ private readonly List _documents = new()
+ {
+ "{ 'foo':'bar', 'bar': 'foo' }",
+ "{ 'foo':'bar', 'bar': 'foo' }",
+ "{ 'qwe':'rty', 'asd': 'fgh' }"
+ };
[TestInitialize]
public void StartUp()
@@ -184,38 +186,45 @@ public void Test_InvalidConnectionString()
Assert.IsTrue(ex.Result.Message.StartsWith("Delete error: System.Exception: DeleteOperation error: MongoDB.Driver.MongoAuthenticationException: Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1."));
}
- private void InsertTestData()
- {
- try
- {
- var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
-
- var doc1 = BsonDocument.Parse(_doc1);
- var doc2 = BsonDocument.Parse(_doc2);
- var doc3 = BsonDocument.Parse(_doc3);
-
- collection.InsertOne(doc1);
- collection.InsertOne(doc2);
- collection.InsertOne(doc3);
- }
- catch (Exception ex)
- {
- throw new Exception(ex.Message);
- }
- }
- private static void DeleteTestData()
- {
- var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
-
- var filter1 = "{'bar':'foo'}";
- var filter2 = "{'qwe':'rty'}";
- var filter3 = "{'asd':'fgh'}";
- collection.DeleteMany(filter1);
- collection.DeleteMany(filter2);
- collection.DeleteMany(filter3);
- }
-
- private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
+ private void InsertTestData()
+ {
+ try
+ {
+ var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
+
+ foreach (var doc in _documents)
+ {
+ collection.InsertOne(BsonDocument.Parse(doc));
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception(ex.Message);
+ }
+ }
+
+ private static void DeleteTestData()
+ {
+ var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
+
+ List filters = new()
+ {
+ "{'bar':'foo'}",
+ "{'qwe':'rty'}",
+ "{'asd':'fgh'}",
+ "{foo:'update'}",
+ "{'foobar':'upsert_create'}",
+ "{'array':'arr'}"
+ };
+
+ foreach (var filter in filters)
+ {
+ collection.DeleteMany(filter);
+ }
+ }
+
+
+ private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
{
var dataBase = GetMongoDatabase(connectionString, database);
var collection = dataBase.GetCollection(collectionName);
diff --git a/Frends.MongoDB.Delete/Frends.MongoDB.Delete/Delete.cs b/Frends.MongoDB.Delete/Frends.MongoDB.Delete/Delete.cs
index 2c9ab94..f1fc913 100644
--- a/Frends.MongoDB.Delete/Frends.MongoDB.Delete/Delete.cs
+++ b/Frends.MongoDB.Delete/Frends.MongoDB.Delete/Delete.cs
@@ -6,6 +6,9 @@
using MongoDB.Driver;
using System.IO;
using System.Threading.Tasks;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Caching;
+using System.Linq;
namespace Frends.MongoDB.Delete;
@@ -14,15 +17,18 @@ namespace Frends.MongoDB.Delete;
///
public class MongoDB
{
- ///
- /// MongoDB delete operation.
- /// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.MongoDB.Delete)
- ///
- /// Input parameters.
- /// Connection parameters.
- /// Token generated by Frends to stop this task.
- /// Object { bool Success, long Count }
- public static async Task Delete([PropertyTab] Input input, [PropertyTab] Connection connection, CancellationToken cancellationToken)
+ internal static readonly ObjectCache ClientCache = MemoryCache.Default;
+ private static readonly CacheItemPolicy _cachePolicy = new() { SlidingExpiration = TimeSpan.FromHours(1) };
+
+ ///
+ /// MongoDB delete operation.
+ /// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.MongoDB.Delete)
+ ///
+ /// Input parameters.
+ /// Connection parameters.
+ /// Token generated by Frends to stop this task.
+ /// Object { bool Success, long Count }
+ public static async Task Delete([PropertyTab] Input input, [PropertyTab] Connection connection, CancellationToken cancellationToken)
{
var collection = GetMongoCollection(connection.ConnectionString, connection.Database, connection.CollectionName);
@@ -41,7 +47,10 @@ public static async Task Delete([PropertyTab] Input input, [PropertyTab]
}
case InputType.Filter:
- return new Result(true, await DeleteOperation(input, BsonDocument.Parse(input.Filter), collection, cancellationToken));
+ if (string.IsNullOrWhiteSpace(input.Filter))
+ throw new ArgumentException("Filter string missing.");
+
+ return new Result(true, await DeleteOperation(input, BsonDocument.Parse(input.Filter), collection, cancellationToken));
case InputType.Filters:
long count = 0;
@@ -80,31 +89,48 @@ private static async Task DeleteOperation(Input input, BsonDocument filter
}
}
- private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
- {
- try
- {
- var dataBase = GetMongoDatabase(connectionString, database);
- var collection = dataBase.GetCollection(collectionName);
- return collection;
- }
- catch (Exception ex)
- {
- throw new Exception($"GetMongoCollection error: {ex}");
- }
- }
+ private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
+ {
+ try
+ {
+ var dataBase = GetMongoDatabase(connectionString, database, collectionName);
+ var collection = dataBase.GetCollection(collectionName);
+ return collection;
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"GetMongoCollection error: {ex}");
+ }
+ }
- private static IMongoDatabase GetMongoDatabase(string connectionString, string database)
- {
- try
- {
- var mongoClient = new MongoClient(connectionString);
- var dataBase = mongoClient.GetDatabase(database);
- return dataBase;
- }
- catch (Exception ex)
- {
- throw new Exception($"GetMongoDatabase error: {ex}");
- }
- }
+ private static IMongoDatabase GetMongoDatabase(string connectionString, string database, string collectionName)
+ {
+ var cacheKey = GetMongoDbCacheKey(connectionString, database, collectionName);
+
+ if (ClientCache.Get(cacheKey) is IMongoDatabase mongoDatabase)
+ {
+ return mongoDatabase;
+ }
+
+ try
+ {
+ var mongoClient = new MongoClient(connectionString);
+ var dataBase = mongoClient.GetDatabase(database);
+
+ ClientCache.Add(cacheKey, dataBase, _cachePolicy);
+
+ return dataBase;
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"GetMongoDatabase error: {ex}");
+ }
+ }
+
+
+ [ExcludeFromCodeCoverage]
+ private static string GetMongoDbCacheKey(string connectionString, string database, string collectionName)
+ {
+ return $"{connectionString.GetHashCode()}:{database}:{collectionName}";
+ }
}
\ No newline at end of file
diff --git a/Frends.MongoDB.Delete/Frends.MongoDB.Delete/Frends.MongoDB.Delete.csproj b/Frends.MongoDB.Delete/Frends.MongoDB.Delete/Frends.MongoDB.Delete.csproj
index 8862a2e..c23d6e8 100644
--- a/Frends.MongoDB.Delete/Frends.MongoDB.Delete/Frends.MongoDB.Delete.csproj
+++ b/Frends.MongoDB.Delete/Frends.MongoDB.Delete/Frends.MongoDB.Delete.csproj
@@ -2,7 +2,7 @@
net6.0
- 1.0.1
+ 2.0.0
Frends
Frends
Frends
@@ -19,33 +19,12 @@
PreserveNewest
-
- true
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
- lib\MongoDB.Driver.dll
-
-
- lib\MongoDB.Driver.Core.dll
-
-
\ No newline at end of file
diff --git a/Frends.MongoDB.Delete/Frends.MongoDB.Delete/lib/MongoDB.Driver.Core.dll b/Frends.MongoDB.Delete/Frends.MongoDB.Delete/lib/MongoDB.Driver.Core.dll
deleted file mode 100644
index ef4f87f..0000000
Binary files a/Frends.MongoDB.Delete/Frends.MongoDB.Delete/lib/MongoDB.Driver.Core.dll and /dev/null differ
diff --git a/Frends.MongoDB.Delete/Frends.MongoDB.Delete/lib/MongoDB.Driver.dll b/Frends.MongoDB.Delete/Frends.MongoDB.Delete/lib/MongoDB.Driver.dll
deleted file mode 100644
index a5f429a..0000000
Binary files a/Frends.MongoDB.Delete/Frends.MongoDB.Delete/lib/MongoDB.Driver.dll and /dev/null differ
diff --git a/Frends.MongoDB.Delete/README.md b/Frends.MongoDB.Delete/README.md
index a02b2d4..63a9483 100644
--- a/Frends.MongoDB.Delete/README.md
+++ b/Frends.MongoDB.Delete/README.md
@@ -8,7 +8,7 @@ Frends Task for MongoDB delete operation.
# Installing
-You can install the Task via Frends UI Task View or you can find the NuGet package from the following NuGet feed https://www.myget.org/F/frends-tasks/api/v2.
+You can install the Task via Frends UI Task View or you can find the NuGet package from the following NuGet feed [NuGet Package](https://www.myget.org/F/frends-tasks/api/v2)
## Building
diff --git a/Frends.MongoDB.Index/CHANGELOG.md b/Frends.MongoDB.Index/CHANGELOG.md
new file mode 100644
index 0000000..346f471
--- /dev/null
+++ b/Frends.MongoDB.Index/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Changelog
+
+## [2.0.0] - 2025-03-12
+### Added
+- Initial implementation
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Files/.env b/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Files/.env
new file mode 100644
index 0000000..1b25ac1
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Files/.env
@@ -0,0 +1 @@
+MONGO_HOST_DATA=/mongodb
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Files/docker-compose.yml b/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Files/docker-compose.yml
new file mode 100644
index 0000000..56b9789
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Files/docker-compose.yml
@@ -0,0 +1,12 @@
+version: '3'
+services:
+ mongo:
+ image: mongo:7
+ environment:
+ - AUTH=yes
+ - MONGO_INITDB_ROOT_USERNAME=admin
+ - MONGO_INITDB_ROOT_PASSWORD=Salakala
+ volumes:
+ - ${MONGO_HOST_DATA}/db:/data/db
+ ports:
+ - "27017:27017"
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Files/testdata.json b/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Files/testdata.json
new file mode 100644
index 0000000..aa8b20f
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Files/testdata.json
@@ -0,0 +1,4 @@
+{
+ "foo": "bar",
+ "bar": "foo"
+}
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Frends.MongoDB.Index.Tests.csproj b/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Frends.MongoDB.Index.Tests.csproj
new file mode 100644
index 0000000..7e8d72b
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/Frends.MongoDB.Index.Tests.csproj
@@ -0,0 +1,25 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+ false
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/UnitTests.cs b/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/UnitTests.cs
new file mode 100644
index 0000000..3aa9d0c
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index.Tests/UnitTests.cs
@@ -0,0 +1,207 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Frends.MongoDB.Index.Definitions;
+using MongoDB.Bson;
+using MongoDB.Driver;
+
+namespace Frends.MongoDB.Index.Tests;
+
+[TestClass]
+public class UnitTests
+{
+ ///
+ /// Run command 'docker-compose up -d' in \Frends.MongoDB.Index.Tests\Files\
+ ///
+
+ private static readonly Connection _connection = new()
+ {
+ ConnectionString = "mongodb://admin:Salakala@localhost:27017/?authSource=admin",
+ Database = "testdb",
+ CollectionName = "testcoll",
+ };
+
+ [TestCleanup]
+ public void CleanUp()
+ {
+ DeleteTestData();
+ }
+
+ [TestMethod]
+ public async Task Test_Create_Single_Field_Index_Generate_Name()
+ {
+ var _input = new Input()
+ {
+ IndexAction = IndexAction.Create,
+ Fields = new FieldNames[]
+ {
+ new() { Value = "foo" }
+ },
+ DropExistingIndex = false
+ };
+
+ var result = await MongoDB.Index(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual("foo_1", result.IndexName);
+ }
+
+ [TestMethod]
+ public async Task Test_Multi_Field_Index_Generate_Name()
+ {
+ var _input = new Input()
+ {
+ IndexAction = IndexAction.Create,
+ Fields = new FieldNames[]
+ {
+ new() { Value = "foo" },
+ new() { Value = "bar", }
+ },
+ DropExistingIndex = false
+ };
+
+ var result = await MongoDB.Index(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual("foo_1_bar_1", result.IndexName);
+ }
+
+ [TestMethod]
+ public async Task Test_Create_Index_With_Given_Name()
+ {
+ var _input = new Input()
+ {
+ IndexAction = IndexAction.Create,
+ Fields = new FieldNames[]
+ {
+ new() { Value = "foobar" }
+ },
+ IndexName = "foobar_index",
+ DropExistingIndex = false
+ };
+
+ var result = await MongoDB.Index(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual("foobar_index", result.IndexName);
+ }
+
+ [TestMethod]
+ public async Task Test_Try_Create_Index_Without_Fields()
+ {
+ var _input = new Input()
+ {
+ IndexAction = IndexAction.Create,
+ IndexName = "nofields",
+ DropExistingIndex = false
+ };
+
+ var ex = await Assert.ThrowsExceptionAsync(async () => await MongoDB.Index(_input, _connection, default));
+ Assert.IsTrue(ex.Message.StartsWith("Index error: System.ArgumentException: Field name(s) missing."));
+ }
+
+ [TestMethod]
+ public async Task Test_Try_Create_Index_Where_Already_Exists()
+ {
+ var _input = new Input()
+ {
+ IndexAction = IndexAction.Create,
+ Fields = new FieldNames[]
+ {
+ new() { Value = "existing" }
+ },
+ DropExistingIndex = false
+ };
+
+ await MongoDB.Index(_input, _connection, default);
+
+ _input = new Input()
+ {
+ IndexAction = IndexAction.Create,
+ Fields = new FieldNames[]
+ {
+ new() { Value = "existing" }
+ },
+ IndexName = "existing_index",
+ DropExistingIndex = false
+ };
+
+ var ex = await Assert.ThrowsExceptionAsync(async () => await MongoDB.Index(_input, _connection, default));
+ Assert.IsTrue(ex.Message.StartsWith("Index error: MongoDB.Driver.MongoCommandException: Command createIndexes failed: Index already exists with a different name: existing_1."));
+ }
+
+ [TestMethod]
+ public async Task Test_Drop_Index_And_Create_With_Same_Name()
+ {
+ var _input = new Input()
+ {
+ IndexAction = IndexAction.Create,
+ Fields = new FieldNames[]
+ {
+ new() { Value = "dropandcreate" }
+ },
+ IndexName = "dropandcreate",
+ DropExistingIndex = false
+ };
+
+ await MongoDB.Index(_input, _connection, default);
+
+ _input = new Input()
+ {
+ IndexAction = IndexAction.Create,
+ Fields = new FieldNames[]
+ {
+ new() { Value = "dropandcreate" },
+ new() { Value = "foo" }
+ },
+ IndexName = "dropandcreate",
+ DropExistingIndex = true
+ };
+
+ var result = await MongoDB.Index(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual("dropandcreate", result.IndexName);
+ }
+
+ [TestMethod]
+ public async Task Test_Drop_Index()
+ {
+ var _input = new Input()
+ {
+ IndexAction = IndexAction.Create,
+ Fields = new FieldNames[]
+ {
+ new() { Value = "drop" }
+ },
+ IndexName = "drop",
+ DropExistingIndex = false
+ };
+
+ await MongoDB.Index(_input, _connection, default);
+
+ _input = new Input()
+ {
+ IndexAction = IndexAction.Drop,
+ IndexName = "drop"
+ };
+
+ var result = await MongoDB.Index(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual("drop", result.IndexName);
+ }
+
+ private static void DeleteTestData()
+ {
+ var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
+ collection.Indexes.DropAll();
+ }
+
+ private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
+ {
+ var dataBase = GetMongoDatabase(connectionString, database);
+ var collection = dataBase.GetCollection(collectionName);
+ return collection;
+ }
+
+ private static IMongoDatabase GetMongoDatabase(string connectionString, string database)
+ {
+ var mongoClient = new MongoClient(connectionString);
+ var dataBase = mongoClient.GetDatabase(database);
+ return dataBase;
+ }
+}
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index.sln b/Frends.MongoDB.Index/Frends.MongoDB.Index.sln
new file mode 100644
index 0000000..179a869
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index.sln
@@ -0,0 +1,37 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.12.35707.178
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Frends.MongoDB.Index", "Frends.MongoDB.Index\Frends.MongoDB.Index.csproj", "{8FB64BB3-C91A-4829-B212-2C967E6830AB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Frends.MongoDB.Index.Tests", "Frends.MongoDB.Index.Tests\Frends.MongoDB.Index.Tests.csproj", "{03BB9C11-A8A1-4E29-A012-F6CC9C862337}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8779CBED-E6FB-4F23-99E2-C6AAC2A85505}"
+ ProjectSection(SolutionItems) = preProject
+ CHANGELOG.md = CHANGELOG.md
+ ..\.github\workflows\Index_build_and_test_on_main.yml = ..\.github\workflows\Index_build_and_test_on_main.yml
+ ..\.github\workflows\Index_build_and_test_on_push.yml = ..\.github\workflows\Index_build_and_test_on_push.yml
+ ..\.github\workflows\Index_release.yml = ..\.github\workflows\Index_release.yml
+ README.md = README.md
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8FB64BB3-C91A-4829-B212-2C967E6830AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8FB64BB3-C91A-4829-B212-2C967E6830AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8FB64BB3-C91A-4829-B212-2C967E6830AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8FB64BB3-C91A-4829-B212-2C967E6830AB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {03BB9C11-A8A1-4E29-A012-F6CC9C862337}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {03BB9C11-A8A1-4E29-A012-F6CC9C862337}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {03BB9C11-A8A1-4E29-A012-F6CC9C862337}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {03BB9C11-A8A1-4E29-A012-F6CC9C862337}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Connection.cs b/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Connection.cs
new file mode 100644
index 0000000..3981ebd
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Connection.cs
@@ -0,0 +1,29 @@
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+
+namespace Frends.MongoDB.Index.Definitions;
+
+///
+/// Connection parameters.
+///
+public class Connection
+{
+ ///
+ /// Connection string.
+ ///
+ /// mongodb://foo:bar@localhost:00000/?authSource=admin
+ [PasswordPropertyText]
+ public string ConnectionString { get; set; }
+
+ ///
+ /// Database.
+ ///
+ /// foo
+ public string Database { get; set; }
+
+ ///
+ /// Collection name.
+ ///
+ /// bar
+ public string CollectionName { get; set; }
+}
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Enums.cs b/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Enums.cs
new file mode 100644
index 0000000..01475c0
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Enums.cs
@@ -0,0 +1,16 @@
+namespace Frends.MongoDB.Index.Definitions;
+
+///
+/// Index options.
+///
+public enum IndexAction
+{
+ ///
+ /// Crrates an index.
+ ///
+ Create,
+ ///
+ /// Deltes an index.
+ ///
+ Drop
+}
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Input.cs b/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Input.cs
new file mode 100644
index 0000000..166bb58
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Input.cs
@@ -0,0 +1,49 @@
+using System.ComponentModel;
+using System.ComponentModel.DataAnnotations;
+using System.Text.RegularExpressions;
+
+namespace Frends.MongoDB.Index.Definitions;
+
+///
+/// Input parameter.
+///
+public class Input
+{
+ ///
+ /// Creates or deletes an index.
+ ///
+ /// IndexAction.Create
+ [DefaultValue(IndexAction.Create)]
+ public IndexAction IndexAction { get; set; }
+
+ ///
+ /// Name of the index, if not specified, MongoDB will generate a name.
+ ///
+ [DefaultValue("")]
+ public string IndexName { get; set; }
+
+ ///
+ /// An array of field name(s) to be included in the index.
+ ///
+ /// name, postalCode
+ [UIHint(nameof(IndexAction), "", IndexAction.Create)]
+ public FieldNames[] Fields { get; set; }
+
+ ///
+ /// Specifies whether to drop the existing index with the same name.
+ ///
+ [UIHint(nameof(IndexAction), "", IndexAction.Create)]
+ public bool DropExistingIndex { get; set; } = false;
+}
+
+///
+/// Input.FieldName values.
+///
+public class FieldNames
+{
+ ///
+ /// Value.
+ ///
+ /// name
+ public string Value { get; set; }
+}
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Result.cs b/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Result.cs
new file mode 100644
index 0000000..6141821
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index/Definitions/Result.cs
@@ -0,0 +1,25 @@
+namespace Frends.MongoDB.Index.Definitions;
+
+///
+/// Task's result.
+///
+public class Result
+{
+ ///
+ /// Operation completed successfully.
+ ///
+ /// true
+ public bool Success { get; private set; }
+
+ ///
+ /// Name of the created index.
+ ///
+ /// 1
+ public string IndexName { get; private set; }
+
+ internal Result(bool success, string indexName)
+ {
+ Success = success;
+ IndexName = indexName;
+ }
+}
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index/Frends.MongoDB.Index.csproj b/Frends.MongoDB.Index/Frends.MongoDB.Index/Frends.MongoDB.Index.csproj
new file mode 100644
index 0000000..8bba96a
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index/Frends.MongoDB.Index.csproj
@@ -0,0 +1,30 @@
+
+
+
+ net6.0
+ 2.0.0
+ Frends
+ Frends
+ Frends
+ Frends
+ Frends
+ MIT
+ true
+ Frends Task for MongoDB index operations.
+ https://frends.com/
+ https://github.com/FrendsPlatform/Frends.MongoDB
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index/FrendsTaskMetadata.json b/Frends.MongoDB.Index/Frends.MongoDB.Index/FrendsTaskMetadata.json
new file mode 100644
index 0000000..07fd006
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index/FrendsTaskMetadata.json
@@ -0,0 +1,7 @@
+{
+ "Tasks": [
+ {
+ "TaskMethod": "Frends.MongoDB.Index.MongoDB.Index"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index/Index.cs b/Frends.MongoDB.Index/Frends.MongoDB.Index/Index.cs
new file mode 100644
index 0000000..a4a77d5
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index/Index.cs
@@ -0,0 +1,151 @@
+using Frends.MongoDB.Index.Definitions;
+using MongoDB.Bson;
+using MongoDB.Driver;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+using System.Runtime.Caching;
+using System.Text;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Frends.MongoDB.Index;
+
+///
+/// MongoDB Task.
+///
+public class MongoDB
+{
+ internal static readonly ObjectCache ClientCache = MemoryCache.Default;
+ private static readonly CacheItemPolicy _cachePolicy = new() { SlidingExpiration = TimeSpan.FromHours(1) };
+
+ ///
+ /// MongoDB index operation.
+ /// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.MongoDB.Index)
+ ///
+ /// Input parameters.
+ /// Connection parameters.
+ /// Token generated by Frends to stop this task.
+ /// Object { bool Success, long Count }
+ public static async Task Index([PropertyTab] Input input, [PropertyTab] Connection connection, CancellationToken cancellationToken)
+ {
+ var collection = GetMongoCollection(connection.ConnectionString, connection.Database, connection.CollectionName);
+
+ try
+ {
+ switch (input.IndexAction)
+ {
+ case IndexAction.Create:
+ if (input.Fields == null || input.Fields?.Length == 0)
+ throw new ArgumentException("Field name(s) missing.");
+
+ return new Result(true, await CreateIndex(collection, input, cancellationToken));
+
+ case IndexAction.Drop:
+ await DropIndex(collection, input, cancellationToken);
+ return new Result(true, input.IndexName);
+
+ default:
+ return new Result(false, "");
+ };
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"Index error: {ex}");
+ }
+
+
+
+
+
+
+
+ //var compoundIndex = new CreateIndexModel(Builders.IndexKeys
+ // .Ascending(m => m.Type)
+ // .Ascending(m => m.Rated));
+ //collection.Indexes.CreateOne(compoundIndex);
+
+ //var foo = new CreateIndexOptions();
+ //foo.Collation = new Collation("en", strength: CollationStrength.Primary);
+ //var indexModel = new CreateIndexModel(Builders.IndexKeys
+ //.Ascending(m => m.)
+ //collection.Indexes.CreateOne(indexModel);
+ }
+
+ private static async Task CreateIndex(IMongoCollection collection, Input input, CancellationToken cancellationToken)
+ {
+ if (input.DropExistingIndex && !string.IsNullOrWhiteSpace(input.IndexName))
+ {
+ await DropIndex(collection, input, cancellationToken);
+ }
+
+ var indexOptions = new CreateIndexOptions { Name = string.IsNullOrWhiteSpace(input.IndexName) ? null : input.IndexName };
+ var indexKeys = Builders.IndexKeys.Combine(input.Fields.Select(field => Builders.IndexKeys.Ascending(field.Value)));
+
+ var indexModel = new CreateIndexModel(indexKeys, indexOptions);
+ var name = await collection.Indexes.CreateOneAsync(indexModel, cancellationToken: cancellationToken);
+ return name;
+ }
+
+ private static async Task DropIndex(IMongoCollection collection, Input input, CancellationToken cancellationToken)
+ {
+ await collection.Indexes.DropOneAsync(input.IndexName, cancellationToken);
+ }
+
+ private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
+ {
+ try
+ {
+ var dataBase = GetMongoDatabase(connectionString, database, collectionName);
+ var collection = dataBase.GetCollection(collectionName);
+ return collection;
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"GetMongoCollection error: {ex}");
+ }
+ }
+
+ private static IMongoDatabase GetMongoDatabase(string connectionString, string database, string collectionName)
+ {
+ var cacheKey = GetMongoDbCacheKey(connectionString, database, collectionName);
+
+ if (ClientCache.Get(cacheKey) is IMongoDatabase mongoDatabase)
+ {
+ return mongoDatabase;
+ }
+
+ try
+ {
+ var mongoClient = new MongoClient(connectionString);
+ var dataBase = mongoClient.GetDatabase(database);
+
+ ClientCache.Add(cacheKey, dataBase, _cachePolicy);
+
+ return dataBase;
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"GetMongoDatabase error: {ex}");
+ }
+ }
+
+ internal static void ClearClientCache()
+ {
+ var cacheKeys = ClientCache.Select(kvp => kvp.Key).ToList();
+ foreach (var cacheKey in cacheKeys)
+ {
+ ClientCache.Remove(cacheKey);
+ }
+ }
+
+ [ExcludeFromCodeCoverage]
+ private static string GetMongoDbCacheKey(string connectionString, string database, string collectionName)
+ {
+ return $"{connectionString.GetHashCode()}:{database}:{collectionName}";
+ }
+}
diff --git a/Frends.MongoDB.Index/Frends.MongoDB.Index/README.md b/Frends.MongoDB.Index/Frends.MongoDB.Index/README.md
new file mode 100644
index 0000000..50a5247
--- /dev/null
+++ b/Frends.MongoDB.Index/Frends.MongoDB.Index/README.md
@@ -0,0 +1,29 @@
+# Frends.MongoDB.Index
+Frends Task for MongoDB index operation.
+
+[](https://opensource.org/licenses/MIT)
+[](https://github.com/FrendsPlatform/Frends.MongoDB/actions)
+
+
+
+# Installing
+
+You can install the Task via Frends UI Task View or you can find the NuGet package from the following NuGet feed https://www.myget.org/F/frends-tasks/api/v2.
+
+## Building
+
+
+Rebuild the project
+
+`dotnet build`
+
+Run tests
+
+Run command `docker-compose up -d` in \Frends.MongoDB.Index.Tests\Files\
+
+`dotnet test`
+
+
+Create a NuGet package
+
+`dotnet pack --configuration Release`
\ No newline at end of file
diff --git a/Frends.MongoDB.Index/README.md b/Frends.MongoDB.Index/README.md
new file mode 100644
index 0000000..be00537
--- /dev/null
+++ b/Frends.MongoDB.Index/README.md
@@ -0,0 +1,29 @@
+# Frends.MongoDB.Index
+Frends Task for MongoDB index operations.
+
+[](https://opensource.org/licenses/MIT)
+[](https://github.com/FrendsPlatform/Frends.MongoDB/actions)
+
+
+
+# Installing
+
+You can install the Task via Frends UI Task View or you can find the NuGet package from the following NuGet feed [NuGet Package](https://www.myget.org/F/frends-tasks/api/v2)
+
+## Building
+
+
+Rebuild the project
+
+`dotnet build`
+
+Run tests
+
+Run commands `docker-compose up -d` in \Frends.MongoDB.Index.Tests\Files\
+
+`dotnet test`
+
+
+Create a NuGet package
+
+`dotnet pack --configuration Release`
\ No newline at end of file
diff --git a/Frends.MongoDB.Insert/CHANGELOG.md b/Frends.MongoDB.Insert/CHANGELOG.md
index 4ba4d54..a0d069d 100644
--- a/Frends.MongoDB.Insert/CHANGELOG.md
+++ b/Frends.MongoDB.Insert/CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog
+## [2.0.0] - 2025-03-12
+### Added
+- Adds caching for the MongoClient connection to improve performance.
+
+### Updated
+- Updated MongoDB.Driver to version 3.2.1
+
+- ### Breaking changes
+- The MongoDB driver drops support for MongoDB Server v3.6 and earlier.
+- The MongoDB driver drops support for .NET Core 2.x and .NET Framework 4.6.
+- Read more about MongoDB driver 3.0 breaking changes [here](https://mongodb.github.io/mongo-csharp-driver/3.0/reference/breaking_changes/)
+
## [1.0.1] - 2023-11-22
### Fixed
- Fixed dll error when importing the Task to Frends by adding local dll reference to the project file.
diff --git a/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Files/docker-compose.yml b/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Files/docker-compose.yml
index cd14b47..56b9789 100644
--- a/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Files/docker-compose.yml
+++ b/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Files/docker-compose.yml
@@ -1,7 +1,7 @@
version: '3'
services:
mongo:
- image: mongo:3
+ image: mongo:7
environment:
- AUTH=yes
- MONGO_INITDB_ROOT_USERNAME=admin
diff --git a/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Files/testdata.json b/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Files/testdata.json
index aa8b20f..bcf5f58 100644
--- a/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Files/testdata.json
+++ b/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Files/testdata.json
@@ -1,4 +1,4 @@
{
- "foo": "bar",
+ "foo": "bar100",
"bar": "foo"
}
\ No newline at end of file
diff --git a/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Frends.MongoDB.Insert.Tests.csproj b/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Frends.MongoDB.Insert.Tests.csproj
index 661d5d4..d9a458b 100644
--- a/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Frends.MongoDB.Insert.Tests.csproj
+++ b/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/Frends.MongoDB.Insert.Tests.csproj
@@ -9,10 +9,13 @@
-
-
-
-
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/UnitTests.cs b/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/UnitTests.cs
index 24da58e..c6e4979 100644
--- a/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/UnitTests.cs
+++ b/Frends.MongoDB.Insert/Frends.MongoDB.Insert.Tests/UnitTests.cs
@@ -1,46 +1,52 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Frends.MongoDB.Insert.Definitions;
+using MongoDB.Bson;
+using MongoDB.Driver;
namespace Frends.MongoDB.Insert.Tests;
[TestClass]
public class UnitTests
{
- /*
+ /*
Run command 'docker-compose up -d' in \Frends.MongoDB.Insert.Tests\Files\
*/
- private static readonly Connection _connection = new()
- {
- ConnectionString = "mongodb://admin:Salakala@localhost:27017/?authSource=admin",
- Database = "testdb",
- CollectionName = "testcoll",
- };
-
- private readonly string _doc1 = "{ \"foo\":\"bar\", \"bar\": \"foo\" }";
- private readonly string _doc2 = "{ \"foo\":\"bar2\", \"bar\": \"foo2\" }";
+ private static readonly Connection _connection = new()
+ {
+ ConnectionString = "mongodb://admin:Salakala@localhost:27017/?authSource=admin",
+ Database = "testdb",
+ CollectionName = "testcoll",
+ };
+ [TestCleanup]
+ public void CleanUp()
+ {
+ DeleteTestData();
+ }
- [TestMethod]
+ [TestMethod]
public async Task Test_Insert_Document()
{
var _input = new Input()
{
InputType = InputType.Document,
- Document = _doc1,
+ Document = "{ 'foo':'bar1', 'bar': 'foo' }",
File = null,
};
var result = await MongoDB.Insert(_input, _connection, default);
- Assert.IsTrue(result.Success.Equals(true) && result.Id != null);
- }
+ Assert.IsTrue(result.Success);
+ Assert.IsNotNull(result.Id);
+ Assert.IsNotNull(GetSingleDocuments("{'foo':'bar1'}"));
+ }
[TestMethod]
public async Task Test_Insert_Documents()
{
- var doc1 = new DocumentValues() { Value = _doc1 };
- var doc2 = new DocumentValues() { Value = _doc2 };
+ var doc1 = new DocumentValues() { Value = "{ 'foo':'bar2', 'bar': 'foo' }" };
+ var doc2 = new DocumentValues() { Value = "{ 'foo':'bar2', 'bar': 'foo' }" };
var _input = new Input()
{
@@ -50,9 +56,11 @@ public async Task Test_Insert_Documents()
File = null,
};
- var result = await MongoDB.Insert(_input, _connection, default);
- Assert.IsTrue(result.Success.Equals(true) && result.Id != null);
- }
+ var result = await MongoDB.Insert(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.IsNotNull(result.Id);
+ Assert.IsTrue(GetDocuments("bar2"));
+ }
[TestMethod]
@@ -65,7 +73,56 @@ public async Task Test_Insert_File()
File = "..//..//..//Files//testdata.json",
};
- var result = await MongoDB.Insert(_input, _connection, default);
- Assert.IsTrue(result.Success.Equals(true) && result.Id != null);
- }
+ var result = await MongoDB.Insert(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.IsNotNull(result.Id);
+ Assert.IsTrue(GetDocuments("bar100"));
+ }
+
+ private static void DeleteTestData()
+ {
+ var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
+
+ List filters = new()
+ {
+ "{'foo':'bar'}",
+ "{'foo':'bar1'}",
+ "{'foo':'bar2'}",
+ "{'foo':'bar3'}",
+ "{'foo':'bar100'}"
+ };
+
+ foreach (var filter in filters)
+ {
+ collection.DeleteMany(filter);
+ }
+ }
+
+ private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
+ {
+ var dataBase = GetMongoDatabase(connectionString, database);
+ var collection = dataBase.GetCollection(collectionName);
+ return collection;
+ }
+
+ private static IMongoDatabase GetMongoDatabase(string connectionString, string database)
+ {
+ var mongoClient = new MongoClient(connectionString);
+ var dataBase = mongoClient.GetDatabase(database);
+ return dataBase;
+ }
+
+ private static bool GetDocuments(string updated)
+ {
+ var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
+ var documents = collection.Find(new BsonDocument()).ToList();
+ var i = documents.Any(x => x.Values.Contains(updated));
+ return i;
+ }
+
+ private static BsonDocument? GetSingleDocuments(string filter)
+ {
+ var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
+ return collection.Find(BsonDocument.Parse(filter)).FirstOrDefault();
+ }
}
\ No newline at end of file
diff --git a/Frends.MongoDB.Insert/Frends.MongoDB.Insert/Frends.MongoDB.Insert.csproj b/Frends.MongoDB.Insert/Frends.MongoDB.Insert/Frends.MongoDB.Insert.csproj
index c76860c..e69a97a 100644
--- a/Frends.MongoDB.Insert/Frends.MongoDB.Insert/Frends.MongoDB.Insert.csproj
+++ b/Frends.MongoDB.Insert/Frends.MongoDB.Insert/Frends.MongoDB.Insert.csproj
@@ -2,7 +2,7 @@
net6.0
- 1.0.1
+ 2.0.0
Frends
Frends
Frends
@@ -19,33 +19,12 @@
PreserveNewest
-
- true
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
- lib\MongoDB.Driver.dll
-
-
- lib\MongoDB.Driver.Core.dll
-
-
\ No newline at end of file
diff --git a/Frends.MongoDB.Insert/Frends.MongoDB.Insert/Insert.cs b/Frends.MongoDB.Insert/Frends.MongoDB.Insert/Insert.cs
index efa3740..ed152de 100644
--- a/Frends.MongoDB.Insert/Frends.MongoDB.Insert/Insert.cs
+++ b/Frends.MongoDB.Insert/Frends.MongoDB.Insert/Insert.cs
@@ -7,6 +7,8 @@
using MongoDB.Bson;
using MongoDB.Driver;
using System.Collections.Generic;
+using System.Runtime.Caching;
+using System.Diagnostics.CodeAnalysis;
namespace Frends.MongoDB.Insert;
@@ -15,15 +17,19 @@ namespace Frends.MongoDB.Insert;
///
public class MongoDB
{
- ///
- /// MongoDB insert operation.
- /// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.MongoDB.Insert)
- ///
- /// Input parameters.
- /// Connection parameters.
- /// Token generated by Frends to stop this task.
- /// Object { bool success, List<string> id }
- public static async Task Insert([PropertyTab] Input input, [PropertyTab] Connection connection, CancellationToken cancellationToken)
+ internal static readonly ObjectCache ClientCache = MemoryCache.Default;
+ private static readonly CacheItemPolicy _cachePolicy = new() { SlidingExpiration = TimeSpan.FromHours(1) };
+
+
+ ///
+ /// MongoDB insert operation.
+ /// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.MongoDB.Insert)
+ ///
+ /// Input parameters.
+ /// Connection parameters.
+ /// Token generated by Frends to stop this task.
+ /// Object { bool success, List<string> id }
+ public static async Task Insert([PropertyTab] Input input, [PropertyTab] Connection connection, CancellationToken cancellationToken)
{
try
{
@@ -63,7 +69,8 @@ public static async Task Insert([PropertyTab] Input input, [PropertyTab]
}
return new Result(true, ids);
- default: return new Result(false, null);
+ default:
+ return new Result(false, null);
};
}
catch (Exception ex)
@@ -72,31 +79,47 @@ public static async Task Insert([PropertyTab] Input input, [PropertyTab]
}
}
- private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
- {
- try
- {
- var dataBase = GetMongoDatabase(connectionString, database);
- var collection = dataBase.GetCollection(collectionName);
- return collection;
- }
- catch (Exception ex)
- {
- throw new Exception($"GetMongoCollection error: {ex}");
- }
- }
+ private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
+ {
+ try
+ {
+ var dataBase = GetMongoDatabase(connectionString, database, collectionName);
+ var collection = dataBase.GetCollection(collectionName);
+ return collection;
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"GetMongoCollection error: {ex}");
+ }
+ }
- private static IMongoDatabase GetMongoDatabase(string connectionString, string database)
- {
- try
- {
- var mongoClient = new MongoClient(connectionString);
- var dataBase = mongoClient.GetDatabase(database);
- return dataBase;
- }
- catch (Exception ex)
- {
- throw new Exception($"GetMongoDatabase error: {ex}");
- }
- }
+ private static IMongoDatabase GetMongoDatabase(string connectionString, string database, string collectionName)
+ {
+ var cacheKey = GetMongoDbCacheKey(connectionString, database, collectionName);
+
+ if (ClientCache.Get(cacheKey) is IMongoDatabase mongoDatabase)
+ {
+ return mongoDatabase;
+ }
+
+ try
+ {
+ var mongoClient = new MongoClient(connectionString);
+ var dataBase = mongoClient.GetDatabase(database);
+
+ ClientCache.Add(cacheKey, dataBase, _cachePolicy);
+
+ return dataBase;
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"GetMongoDatabase error: {ex}");
+ }
+ }
+
+ [ExcludeFromCodeCoverage]
+ private static string GetMongoDbCacheKey(string connectionString, string database, string collectionName)
+ {
+ return $"{connectionString.GetHashCode()}:{database}:{collectionName}";
+ }
}
\ No newline at end of file
diff --git a/Frends.MongoDB.Insert/Frends.MongoDB.Insert/lib/MongoDB.Driver.Core.dll b/Frends.MongoDB.Insert/Frends.MongoDB.Insert/lib/MongoDB.Driver.Core.dll
deleted file mode 100644
index ef4f87f..0000000
Binary files a/Frends.MongoDB.Insert/Frends.MongoDB.Insert/lib/MongoDB.Driver.Core.dll and /dev/null differ
diff --git a/Frends.MongoDB.Insert/Frends.MongoDB.Insert/lib/MongoDB.Driver.dll b/Frends.MongoDB.Insert/Frends.MongoDB.Insert/lib/MongoDB.Driver.dll
deleted file mode 100644
index a5f429a..0000000
Binary files a/Frends.MongoDB.Insert/Frends.MongoDB.Insert/lib/MongoDB.Driver.dll and /dev/null differ
diff --git a/Frends.MongoDB.Insert/README.md b/Frends.MongoDB.Insert/README.md
index b497a31..397d3ac 100644
--- a/Frends.MongoDB.Insert/README.md
+++ b/Frends.MongoDB.Insert/README.md
@@ -8,7 +8,7 @@ Frends Task for MongoDB insert operation.
# Installing
-You can install the Task via Frends UI Task View or you can find the NuGet package from the following NuGet feed https://www.myget.org/F/frends-tasks/api/v2.
+You can install the Task via Frends UI Task View or you can find the NuGet package from the following NuGet feed [NuGet Package](https://www.myget.org/F/frends-tasks/api/v2)
## Building
diff --git a/Frends.MongoDB.Query/CHANGELOG.md b/Frends.MongoDB.Query/CHANGELOG.md
index 7905125..372ec7c 100644
--- a/Frends.MongoDB.Query/CHANGELOG.md
+++ b/Frends.MongoDB.Query/CHANGELOG.md
@@ -1,5 +1,18 @@
# Changelog
+## [2.0.0] - 2025-03-12
+### Added
+- Adds caching for the MongoClient connection to improve performance.
+- Option to query single or multiple documents
+
+### Updated
+- Updated MongoDB.Driver to version 3.2.1
+
+### Breaking changes
+- The MongoDB driver drops support for MongoDB Server v3.6 and earlier.
+- The MongoDB driver drops support for .NET Core 2.x and .NET Framework 4.6.
+- Read more about MongoDB driver 3.0 breaking changes [here](https://mongodb.github.io/mongo-csharp-driver/3.0/reference/breaking_changes/)
+
## [1.0.1] - 2023-11-23
### Fixed
- Fixed dll error when importing the Task to Frends by adding local dll reference to the project file.
diff --git a/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/Files/docker-compose.yml b/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/Files/docker-compose.yml
index cd14b47..56b9789 100644
--- a/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/Files/docker-compose.yml
+++ b/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/Files/docker-compose.yml
@@ -1,7 +1,7 @@
version: '3'
services:
mongo:
- image: mongo:3
+ image: mongo:7
environment:
- AUTH=yes
- MONGO_INITDB_ROOT_USERNAME=admin
diff --git a/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/Frends.MongoDB.Query.Tests.csproj b/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/Frends.MongoDB.Query.Tests.csproj
index 9de03de..065aa73 100644
--- a/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/Frends.MongoDB.Query.Tests.csproj
+++ b/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/Frends.MongoDB.Query.Tests.csproj
@@ -9,16 +9,15 @@
-
-
-
-
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
-
-
-
-
diff --git a/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/UnitTests.cs b/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/UnitTests.cs
index a67931f..c18891a 100644
--- a/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/UnitTests.cs
+++ b/Frends.MongoDB.Query/Frends.MongoDB.Query.Tests/UnitTests.cs
@@ -1,30 +1,34 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Frends.MongoDB.Query.Definitions;
-using MongoDB.Bson;
using MongoDB.Driver;
+using MongoDB.Bson.IO;
+using MongoDB.Bson;
namespace Frends.MongoDB.Query.Tests;
[TestClass]
public class UnitTests
{
- /*
+ /*
Run command 'docker-compose up -d' in \Frends.MongoDB.Query.Tests\Files\
*/
- private static readonly Connection _connection = new()
- {
- ConnectionString = "mongodb://admin:Salakala@localhost:27017/?authSource=admin",
- Database = "testdb",
- CollectionName = "testcoll",
- };
-
- private readonly string _doc1 = "{ \"foo\":\"bar\", \"bar\": \"foo\" }";
- private readonly string _doc2 = "{ \"foo\":\"bar\", \"bar\": \"foo\" }";
- private readonly string _doc3 = "{ \"qwe\":\"rty\", \"asd\": \"fgh\" }";
-
-
- [TestInitialize]
+ private static readonly Connection _connection = new()
+ {
+ ConnectionString = "mongodb://admin:Salakala@localhost:27017/?authSource=admin",
+ Database = "testdb",
+ CollectionName = "testcoll",
+ };
+
+ private readonly List _documents = new()
+ {
+ "{ 'foo':'bar', 'bar': 'foo' }",
+ "{ 'foo':'bar', 'bar': 'foo' }",
+ "{ 'foo':99, 'bar': 'foo' }",
+ "{ 'qwe':'rty', 'asd': 'fgh' }"
+ };
+
+ [TestInitialize]
public void StartUp()
{
InsertTestData();
@@ -33,16 +37,17 @@ public void StartUp()
[TestCleanup]
public void CleanUp()
{
- DeleteTestData();
- }
+ DeleteTestData();
+ }
[TestMethod]
public void Test_Query_TwoResults()
{
var _input = new Input()
{
- Filter = "{'foo':'bar'}"
- };
+ Filter = "{'foo':'bar'}",
+ QueryOptions = QueryOptions.QueryMany
+ };
var result = MongoDB.Query(_input, _connection, default);
Assert.IsTrue(result.Success);
@@ -55,14 +60,44 @@ public void Test_Query_OneResults()
var _input = new Input()
{
Filter = "{'qwe':'rty'}"
- };
+ };
var result = MongoDB.Query(_input, _connection, default);
Assert.IsTrue(result.Success);
Assert.AreEqual(1, result.Data.Count);
}
- [TestMethod]
+ [TestMethod]
+ public void Test_Query_RelaxedExtendedJson()
+ {
+ var _input = new Input()
+ {
+ Filter = "{'foo':99}",
+ JsonOutputMode = Definitions.JsonOutputMode.RelaxedExtendedJson,
+ };
+
+ var result = MongoDB.Query(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual(1, result.Data.Count);
+ Assert.IsFalse(result.Data[0].Contains("$numberInt"));
+ }
+
+ [TestMethod]
+ public void Test_Query_CanonicalExtendedJson()
+ {
+ var _input = new Input()
+ {
+ Filter = "{'foo':99}",
+ JsonOutputMode = Definitions.JsonOutputMode.CanonicalExtendedJson,
+ };
+
+ var result = MongoDB.Query(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual(1, result.Data.Count);
+ Assert.IsTrue(result.Data[0].Contains("$numberInt"));
+ }
+
+ [TestMethod]
public void Test_Query_NotFoundFilter()
{
var _input = new Input()
@@ -78,7 +113,7 @@ public void Test_Query_NotFoundFilter()
[TestMethod]
public void Test_EmptyQuery()
{
- var ex = Assert.ThrowsException(() => MongoDB.Query(new Input { Filter = "" }, _connection, default));
+ var ex = Assert.ThrowsException(() => MongoDB.Query(new Input { Filter = "" }, _connection, default));
Assert.AreEqual("Query error: Filter can't be null.", ex.Message);
}
@@ -101,28 +136,44 @@ public void Test_InvalidConnectionString()
Assert.IsTrue(ex.Message.StartsWith("Query error: MongoDB.Driver.MongoAuthenticationException: Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1."));
}
- private void InsertTestData()
- {
- try
- {
- var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
-
- var doc1 = BsonDocument.Parse(_doc1);
- var doc2 = BsonDocument.Parse(_doc2);
- var doc3 = BsonDocument.Parse(_doc3);
-
- collection.InsertOne(doc1);
- collection.InsertOne(doc2);
- collection.InsertOne(doc3);
- }
- catch (Exception ex)
- {
-
- throw new Exception(ex.Message);
- }
- }
-
- private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
+ private void InsertTestData()
+ {
+ try
+ {
+ var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
+
+ foreach (var doc in _documents)
+ {
+ collection.InsertOne(BsonDocument.Parse(doc));
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new Exception(ex.Message);
+ }
+ }
+
+ private static void DeleteTestData()
+ {
+ var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
+
+ List filters = new()
+ {
+ "{'bar':'foo'}",
+ "{'qwe':'rty'}",
+ "{'asd':'fgh'}",
+ "{foo:'update'}",
+ "{'foobar':'upsert_create'}",
+ "{'array':'arr'}"
+ };
+
+ foreach (var filter in filters)
+ {
+ collection.DeleteMany(filter);
+ }
+ }
+
+ private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
{
var dataBase = GetMongoDatabase(connectionString, database);
var collection = dataBase.GetCollection(collectionName);
@@ -135,16 +186,4 @@ private static IMongoDatabase GetMongoDatabase(string connectionString, string d
var dataBase = mongoClient.GetDatabase(database);
return dataBase;
}
-
- private static void DeleteTestData()
- {
- var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
-
- var filter1 = "{'bar':'foo'}";
- var filter2 = "{'qwe':'rty'}";
- var filter3 = "{'asd':'fgh'}";
- collection.DeleteMany(filter1);
- collection.DeleteMany(filter2);
- collection.DeleteMany(filter3);
- }
}
\ No newline at end of file
diff --git a/Frends.MongoDB.Query/Frends.MongoDB.Query/Definitions/Enums.cs b/Frends.MongoDB.Query/Frends.MongoDB.Query/Definitions/Enums.cs
new file mode 100644
index 0000000..b69d3e6
--- /dev/null
+++ b/Frends.MongoDB.Query/Frends.MongoDB.Query/Definitions/Enums.cs
@@ -0,0 +1,37 @@
+namespace Frends.MongoDB.Query.Definitions;
+///
+/// Query options.
+///
+public enum QueryOptions
+{
+ ///
+ /// Returns the first document that match a specified filter even though multiple documents may match the specified filter.
+ ///
+ QueryOne,
+
+ ///
+ /// Returns all documents that match a specified filter.
+ ///
+ QueryMany,
+}
+
+///
+/// Represents the output mode of a JsonWriter.
+///
+public enum JsonOutputMode
+{
+ ///
+ /// Use a format that can be pasted in to the MongoDB shell.
+ ///
+ Shell,
+
+ ///
+ /// Output canonical extended JSON.
+ ///
+ CanonicalExtendedJson,
+
+ ///
+ /// Output relaxed extended JSON.
+ ///
+ RelaxedExtendedJson,
+}
\ No newline at end of file
diff --git a/Frends.MongoDB.Query/Frends.MongoDB.Query/Definitions/Input.cs b/Frends.MongoDB.Query/Frends.MongoDB.Query/Definitions/Input.cs
index c23a5a4..f0495cd 100644
--- a/Frends.MongoDB.Query/Frends.MongoDB.Query/Definitions/Input.cs
+++ b/Frends.MongoDB.Query/Frends.MongoDB.Query/Definitions/Input.cs
@@ -1,13 +1,30 @@
-namespace Frends.MongoDB.Query.Definitions;
+using System.ComponentModel;
+
+namespace Frends.MongoDB.Query.Definitions;
///
/// Input parameter.
///
public class Input
{
- ///
- /// Filter document.
- ///
- /// {'foo':'bar'}
- public string Filter { get; set; }
+ ///
+ /// Query single or multiple documents.
+ ///
+ /// QueryOptions.QueryMany
+ [DefaultValue(QueryOptions.QueryMany)]
+ public QueryOptions QueryOptions { get; set; }
+
+
+ ///
+ /// Filter document.
+ ///
+ /// {'foo':'bar'}
+ public string Filter { get; set; }
+
+ ///
+ /// Json output mode.
+ ///
+ /// JsonOutputMode.RelaxedExtendedJson
+ [DefaultValue(JsonOutputMode.RelaxedExtendedJson)]
+ public JsonOutputMode JsonOutputMode { get; set; }
}
\ No newline at end of file
diff --git a/Frends.MongoDB.Query/Frends.MongoDB.Query/Frends.MongoDB.Query.csproj b/Frends.MongoDB.Query/Frends.MongoDB.Query/Frends.MongoDB.Query.csproj
index 6edb61a..4e0c768 100644
--- a/Frends.MongoDB.Query/Frends.MongoDB.Query/Frends.MongoDB.Query.csproj
+++ b/Frends.MongoDB.Query/Frends.MongoDB.Query/Frends.MongoDB.Query.csproj
@@ -2,7 +2,7 @@
net6.0
- 1.0.1
+ 1.0.3
Frends
Frends
Frends
@@ -19,33 +19,12 @@
PreserveNewest
-
- true
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
- lib\MongoDB.Driver.dll
-
-
- lib\MongoDB.Driver.Core.dll
-
-
\ No newline at end of file
diff --git a/Frends.MongoDB.Query/Frends.MongoDB.Query/FrendsTaskMetadata.json b/Frends.MongoDB.Query/Frends.MongoDB.Query/FrendsTaskMetadata.json
index df26bd0..24c71e1 100644
--- a/Frends.MongoDB.Query/Frends.MongoDB.Query/FrendsTaskMetadata.json
+++ b/Frends.MongoDB.Query/Frends.MongoDB.Query/FrendsTaskMetadata.json
@@ -1,7 +1,7 @@
{
- "Tasks": [
- {
- "TaskMethod": "Frends.MongoDB.Query.MongoDB.Query"
- }
- ]
+ "Tasks": [
+ {
+ "TaskMethod": "Frends.MongoDB.Query.MongoDB.Query"
+ }
+ ]
}
\ No newline at end of file
diff --git a/Frends.MongoDB.Query/Frends.MongoDB.Query/Query.cs b/Frends.MongoDB.Query/Frends.MongoDB.Query/Query.cs
index 5846f62..4d3e34c 100644
--- a/Frends.MongoDB.Query/Frends.MongoDB.Query/Query.cs
+++ b/Frends.MongoDB.Query/Frends.MongoDB.Query/Query.cs
@@ -2,10 +2,13 @@
using System.ComponentModel;
using System;
using System.Threading;
+using Mongo = MongoDB;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Bson.IO;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Caching;
namespace Frends.MongoDB.Query;
@@ -14,31 +17,44 @@ namespace Frends.MongoDB.Query;
///
public class MongoDB
{
- ///
- /// MongoDB query operation.
- /// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.MongoDB.Query)
- ///
- /// Input parameters.
- /// Connection parameters.
- /// Token generated by Frends to stop this task.
- /// Object { bool Success, List<string> Data }
- public static Result Query([PropertyTab] Input input, [PropertyTab] Connection connection, CancellationToken cancellationToken)
+ internal static readonly ObjectCache ClientCache = MemoryCache.Default;
+ private static readonly CacheItemPolicy _cachePolicy = new() { SlidingExpiration = TimeSpan.FromHours(1) };
+
+
+ ///
+ /// MongoDB query operation.
+ /// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.MongoDB.Query)
+ ///
+ /// Input parameters.
+ /// Connection parameters.
+ /// Token generated by Frends to stop this task.
+ /// Object { bool Success, List<string> Data }
+ public static Result Query([PropertyTab] Input input, [PropertyTab] Connection connection, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(input.Filter))
- throw new Exception("Query error: Filter can't be null.");
+ throw new ArgumentException("Query error: Filter can't be null.");
try
{
var li = new List();
- var jsonSettings = new JsonWriterSettings { OutputMode = JsonOutputMode.CanonicalExtendedJson };
+ var jsonSettings = new JsonWriterSettings { OutputMode = ( Mongo.Bson.IO.JsonOutputMode)(int)input.JsonOutputMode };
var collection = GetMongoCollection(connection.ConnectionString, connection.Database, connection.CollectionName);
- var cursor = collection.Find(input.Filter).ToCursor(cancellationToken);
-
- foreach (var document in cursor.ToEnumerable(cancellationToken: cancellationToken))
- li.Add(document.ToJson(jsonSettings));
+
+ if (input.QueryOptions == QueryOptions.QueryOne)
+ {
+ var document = collection.Find(input.Filter).FirstOrDefault(cancellationToken);
+ if (document != null)
+ li.Add(document.ToJson(jsonSettings));
+ }
+ else
+ {
+ var cursor = collection.Find(input.Filter).ToCursor(cancellationToken);
+ foreach (var document in cursor.ToEnumerable(cancellationToken: cancellationToken))
+ li.Add(document.ToJson(jsonSettings));
+ }
+
return new Result(true, li);
-
}
catch (Exception ex)
{
@@ -46,31 +62,47 @@ public static Result Query([PropertyTab] Input input, [PropertyTab] Connection c
}
}
- private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
- {
- try
- {
- var dataBase = GetMongoDatabase(connectionString, database);
- var collection = dataBase.GetCollection(collectionName);
- return collection;
- }
- catch (Exception ex)
- {
- throw new Exception($"GetMongoCollection error: {ex}");
- }
- }
+ private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
+ {
+ try
+ {
+ var dataBase = GetMongoDatabase(connectionString, database, collectionName);
+ var collection = dataBase.GetCollection(collectionName);
+ return collection;
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"GetMongoCollection error: {ex}");
+ }
+ }
- private static IMongoDatabase GetMongoDatabase(string connectionString, string database)
- {
- try
- {
- var mongoClient = new MongoClient(connectionString);
- var dataBase = mongoClient.GetDatabase(database);
- return dataBase;
- }
- catch (Exception ex)
- {
- throw new Exception($"GetMongoDatabase error: {ex}");
- }
- }
+ private static IMongoDatabase GetMongoDatabase(string connectionString, string database, string collectionName)
+ {
+ var cacheKey = GetMongoDbCacheKey(connectionString, database, collectionName);
+
+ if (ClientCache.Get(cacheKey) is IMongoDatabase mongoDatabase)
+ {
+ return mongoDatabase;
+ }
+
+ try
+ {
+ var mongoClient = new MongoClient(connectionString);
+ var dataBase = mongoClient.GetDatabase(database);
+
+ ClientCache.Add(cacheKey, dataBase, _cachePolicy);
+
+ return dataBase;
+ }
+ catch (Exception ex)
+ {
+ throw new Exception($"GetMongoDatabase error: {ex}");
+ }
+ }
+
+ [ExcludeFromCodeCoverage]
+ private static string GetMongoDbCacheKey(string connectionString, string database, string collectionName)
+ {
+ return $"{connectionString.GetHashCode()}:{database}:{collectionName}";
+ }
}
\ No newline at end of file
diff --git a/Frends.MongoDB.Query/Frends.MongoDB.Query/lib/MongoDB.Driver.Core.dll b/Frends.MongoDB.Query/Frends.MongoDB.Query/lib/MongoDB.Driver.Core.dll
deleted file mode 100644
index ef4f87f..0000000
Binary files a/Frends.MongoDB.Query/Frends.MongoDB.Query/lib/MongoDB.Driver.Core.dll and /dev/null differ
diff --git a/Frends.MongoDB.Query/Frends.MongoDB.Query/lib/MongoDB.Driver.dll b/Frends.MongoDB.Query/Frends.MongoDB.Query/lib/MongoDB.Driver.dll
deleted file mode 100644
index a5f429a..0000000
Binary files a/Frends.MongoDB.Query/Frends.MongoDB.Query/lib/MongoDB.Driver.dll and /dev/null differ
diff --git a/Frends.MongoDB.Query/README.md b/Frends.MongoDB.Query/README.md
index 5c3a39a..6f73be1 100644
--- a/Frends.MongoDB.Query/README.md
+++ b/Frends.MongoDB.Query/README.md
@@ -8,7 +8,7 @@ Frends Task for MongoDB query operation.
# Installing
-You can install the Task via Frends UI Task View or you can find the NuGet package from the following NuGet feed https://www.myget.org/F/frends-tasks/api/v2.
+You can install the Task via Frends UI Task View or you can find the NuGet package from the following NuGet feed [NuGet Package](https://www.myget.org/F/frends-tasks/api/v2)
## Building
diff --git a/Frends.MongoDB.Update/CHANGELOG.md b/Frends.MongoDB.Update/CHANGELOG.md
index dc11050..95f5bd8 100644
--- a/Frends.MongoDB.Update/CHANGELOG.md
+++ b/Frends.MongoDB.Update/CHANGELOG.md
@@ -1,5 +1,19 @@
# Changelog
+## [2.0.0] - 2025-03-12
+### Added
+- Adds caching for the MongoClient connection to improve performance.
+- Adds support for array filter for an update operation.
+- Option to use upsert when updating documents.
+
+### Updated
+- Updated MongoDB.Driver to version 3.2.1
+
+### Breaking changes
+- The MongoDB driver drops support for MongoDB Server v3.6 and earlier.
+- The MongoDB driver drops support for .NET Core 2.x and .NET Framework 4.6.
+- Read more about MongoDB driver 3.0 breaking changes [here](https://mongodb.github.io/mongo-csharp-driver/3.0/reference/breaking_changes/)
+
## [1.0.1] - 2023-11-23
### Fixed
- Fixed dll error when importing the Task to Frends by adding local dll reference to the project file.
diff --git a/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Files/docker-compose.yml b/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Files/docker-compose.yml
index cd14b47..56b9789 100644
--- a/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Files/docker-compose.yml
+++ b/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Files/docker-compose.yml
@@ -1,7 +1,7 @@
version: '3'
services:
mongo:
- image: mongo:3
+ image: mongo:7
environment:
- AUTH=yes
- MONGO_INITDB_ROOT_USERNAME=admin
diff --git a/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Frends.MongoDB.Update.Tests.csproj b/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Frends.MongoDB.Update.Tests.csproj
index 9e4fec7..d57bb41 100644
--- a/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Frends.MongoDB.Update.Tests.csproj
+++ b/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Frends.MongoDB.Update.Tests.csproj
@@ -4,23 +4,19 @@
net6.0
enable
enable
-
false
-
-
-
-
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
-
-
-
-
-
-
diff --git a/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Properties/launchSettings.json b/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Properties/launchSettings.json
new file mode 100644
index 0000000..d5af7ad
--- /dev/null
+++ b/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/Properties/launchSettings.json
@@ -0,0 +1,10 @@
+{
+ "profiles": {
+ "Frends.MongoDB.Update.Tests": {
+ "commandName": "Project",
+ "environmentVariables": {
+ "MONGODB_TEST_CONNECTION_STRING": "mongodb://admin:Salakala@192.168.10.113:27017/?authSource=admin"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/UnitTests.cs b/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/UnitTests.cs
index b672545..cb5a62a 100644
--- a/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/UnitTests.cs
+++ b/Frends.MongoDB.Update/Frends.MongoDB.Update.Tests/UnitTests.cs
@@ -8,23 +8,26 @@ namespace Frends.MongoDB.Update.Tests;
[TestClass]
public class UnitTests
{
- ///
- /// Run command 'docker-compose up -d' in \Frends.MongoDB.Update.Tests\Files\
- ///
-
- private static readonly Connection _connection = new()
- {
- ConnectionString = "mongodb://admin:Salakala@localhost:27017/?authSource=admin",
- Database = "testdb",
- CollectionName = "testcoll",
- };
-
- private readonly string _doc1 = "{ 'foo':'bar', 'bar': 'foo' }";
- private readonly string _doc2 = "{ 'foo':'bar', 'bar': 'foo' }";
- private readonly string _doc3 = "{ 'qwe':'rty', 'asd': 'fgh' }";
-
-
- [TestInitialize]
+ ///
+ /// Run command 'docker-compose up -d' in \Frends.MongoDB.Update.Tests\Files\
+ ///
+
+ private static readonly Connection _connection = new()
+ {
+ ConnectionString = "mongodb://admin:Salakala@localhost:27017/?authSource=admin",
+ Database = "testdb",
+ CollectionName = "testcoll",
+ };
+
+ private readonly List _documents = new()
+ {
+ "{ 'foo':'bar', 'bar': 'foo' }",
+ "{ 'foo':'bar', 'bar': 'foo' }",
+ "{ 'qwe':'rty', 'asd': 'fgh' }",
+ "{ 'array':'arr', 'children': [{'child':1, 'value': 'val1' }, {'child':2, 'value': 'val2' }] }"
+ };
+
+ [TestInitialize]
public void StartUp()
{
InsertTestData();
@@ -33,10 +36,10 @@ public void StartUp()
[TestCleanup]
public void CleanUp()
{
- UpdateTestData();
- }
+ DeleteTestData();
+ }
- [TestMethod]
+ [TestMethod]
public async Task Test_Update_NotFound()
{
var _input = new Input()
@@ -62,10 +65,11 @@ public async Task Test_Update_Single_UpdateOne()
{
InputType = InputType.Filter,
UpdateOptions = Definitions.UpdateOptions.UpdateOne,
- Filter = "{'foo':'bar'}",
- Filters = null,
+ Filter = "{'foo':'bar'}",
+ Filters = null,
File = null,
- UpdateString = "{$set: {foo:'update'}}"
+ UpdateString = "{$set: {foo:'update'}}",
+ Upsert = true
};
var result = await MongoDB.Update(_input, _connection, default);
@@ -84,8 +88,9 @@ public async Task Test_Update_Single_UpdateMany()
Filter = "{'foo':'bar'}",
Filters = null,
File = null,
- UpdateString = "{$set: {foo:'update'}}"
- };
+ UpdateString = "{$set: {foo:'update'}}",
+ Upsert = true
+ };
var result = await MongoDB.Update(_input, _connection, default);
Assert.IsTrue(result.Success);
@@ -190,8 +195,8 @@ public void Test_InvalidConnectionString()
var connection = new Connection
{
- ConnectionString = "mongodb://admin:Incorrect@localhost:27017/?authSource=invalid",
- CollectionName = _connection.CollectionName,
+ ConnectionString = "mongodb://admin:Incorrect@localhost:27017/?authSource=invalid",
+ CollectionName = _connection.CollectionName,
Database = _connection.Database,
};
@@ -199,36 +204,144 @@ public void Test_InvalidConnectionString()
Assert.IsTrue(ex.Result.Message.StartsWith("Update error: System.Exception: UpdateOperation error: MongoDB.Driver.MongoAuthenticationException: Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1."));
}
- private void InsertTestData()
+ [TestMethod]
+ public async Task Test_Upsert_Create_Document()
+ {
+ var _input = new Input()
+ {
+ InputType = InputType.Filter,
+ UpdateOptions = Definitions.UpdateOptions.UpdateOne,
+ Filter = "{'foobar':'upsert_create'}",
+ Filters = null,
+ File = null,
+ UpdateString = "{$set: {foobar:'upsert_create'}}",
+ Upsert = true
+ };
+
+ var result = await MongoDB.Update(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual(1, result.Count);
+ Assert.IsTrue(GetDocuments("upsert_create"));
+ }
+
+ [TestMethod]
+ public async Task Test_Upsert_Dont_Create_Document()
+ {
+ var _input = new Input()
+ {
+ InputType = InputType.Filter,
+ UpdateOptions = Definitions.UpdateOptions.UpdateOne,
+ Filter = "{'foobar':'upsert_none'}",
+ Filters = null,
+ File = null,
+ UpdateString = "{$set: {foo:'upsert_none'}}",
+ Upsert = false
+ };
+
+ var result = await MongoDB.Update(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual(0, result.Count);
+ Assert.IsFalse(GetDocuments("upsert_none"));
+ }
+
+ [TestMethod]
+ public void Test_Failing_When_No_Filter()
+ {
+ var _input = new Input()
+ {
+ InputType = InputType.Filter,
+ UpdateOptions = Definitions.UpdateOptions.UpdateMany,
+ Filter = "",
+ Filters = null,
+ File = null,
+ UpdateString = "{$set: {foo:'update'}}",
+ Upsert = true
+ };
+
+ var ex = Assert.ThrowsExceptionAsync(async () => await MongoDB.Update(_input, _connection, default));
+ Assert.IsTrue(ex.Result.Message.StartsWith("Update error: System.ArgumentException: Filter string missing."));
+ }
+
+ [TestMethod]
+ public async Task Test_Update_Item_In_Child_Array()
+ {
+ var _input = new Input()
+ {
+ InputType = InputType.Filter,
+ UpdateOptions = Definitions.UpdateOptions.UpdateOne,
+ Filter = "{'array':'arr'}",
+ Filters = null,
+ File = null,
+ UpdateString = "{$set: {'children.$[i].value': 'new_value'}}",
+ ArrayFilter = "{'i.child': 1, 'i.value': 'val1'}",
+ Upsert = false
+ };
+
+ var result = await MongoDB.Update(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual(1, result.Count);
+
+ var document = GetSingleDocuments(_input.Filter);
+ Assert.IsNotNull(document);
+ Assert.AreEqual("new_value", document["children"].AsBsonArray[0]["value"].AsString);
+ }
+
+ [TestMethod]
+ public async Task Test_Dont_Update_Item_In_Child_Array()
+ {
+ var _input = new Input()
+ {
+ InputType = InputType.Filter,
+ UpdateOptions = Definitions.UpdateOptions.UpdateOne,
+ Filter = "{'array':'arr'}",
+ Filters = null,
+ File = null,
+ UpdateString = "{$set: {'children.$[i].value': 'new_value'}}",
+ ArrayFilter = "{'i.child': 1, 'i.value': 'val2'}",
+ Upsert = false
+ };
+
+ var result = await MongoDB.Update(_input, _connection, default);
+ Assert.IsTrue(result.Success);
+ Assert.AreEqual(0, result.Count);
+ }
+
+ private void InsertTestData()
{
try
{
var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
- var doc1 = BsonDocument.Parse(_doc1);
- var doc2 = BsonDocument.Parse(_doc2);
- var doc3 = BsonDocument.Parse(_doc3);
-
- collection.InsertOne(doc1);
- collection.InsertOne(doc2);
- collection.InsertOne(doc3);
- }
+ foreach (var doc in _documents)
+ {
+ collection.InsertOne(BsonDocument.Parse(doc));
+ }
+ }
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
- private static void UpdateTestData()
+
+ private static void DeleteTestData()
{
var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
- var filter1 = "{'bar':'foo'}";
- var filter2 = "{'qwe':'rty'}";
- var filter3 = "{'asd':'fgh'}";
- collection.DeleteMany(filter1);
- collection.DeleteMany(filter2);
- collection.DeleteMany(filter3);
- }
+ List filters = new()
+ {
+ "{'bar':'foo'}",
+ "{'qwe':'rty'}",
+ "{'asd':'fgh'}",
+ "{foo:'update'}",
+ "{'foobar':'upsert_create'}",
+ "{'array':'arr'}"
+ };
+
+ foreach (var filter in filters)
+ {
+ collection.DeleteMany(filter);
+ }
+ }
private static IMongoCollection GetMongoCollection(string connectionString, string database, string collectionName)
{
@@ -251,4 +364,10 @@ private static bool GetDocuments(string updated)
var i = documents.Any(x => x.Values.Contains(updated));
return i;
}
+
+ private static BsonDocument? GetSingleDocuments(string filter)
+ {
+ var collection = GetMongoCollection(_connection.ConnectionString, _connection.Database, _connection.CollectionName);
+ return collection.Find(BsonDocument.Parse(filter)).FirstOrDefault();
+ }
}
\ No newline at end of file
diff --git a/Frends.MongoDB.Update/Frends.MongoDB.Update/Definitions/Input.cs b/Frends.MongoDB.Update/Frends.MongoDB.Update/Definitions/Input.cs
index 0a0a617..d73ab40 100644
--- a/Frends.MongoDB.Update/Frends.MongoDB.Update/Definitions/Input.cs
+++ b/Frends.MongoDB.Update/Frends.MongoDB.Update/Definitions/Input.cs
@@ -1,5 +1,6 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
+using System.Text.RegularExpressions;
namespace Frends.MongoDB.Update.Definitions;
@@ -35,11 +36,11 @@ public class Input
[UIHint(nameof(InputType), "", InputType.Filter)]
public string Filter { get; set; }
- ///
- /// An array of filter(s) to be processed one by one.
- ///
- /// {{'foo':'bar'}, {'bar':'foo'}}
- [UIHint(nameof(InputType), "", InputType.Filters)]
+ ///
+ /// An array of filter(s) to be processed one by one.
+ ///
+ /// {{'foo':'bar'}, {'bar':'foo'}}
+ [UIHint(nameof(InputType), "", InputType.Filters)]
public DocumentValues[] Filters { get; set; }
///
@@ -48,6 +49,19 @@ public class Input
/// c:\temp\file.json
[UIHint(nameof(InputType), "", InputType.File)]
public string File { get; set; }
+
+ ///
+ /// Specifies the array filter for an update operation.
+ /// In the example below this UpdateString is used: {$set: {'children.$[i].value': 'new_value'}}
+ ///
+ /// {'i.child': 1, 'i.value': 'val1'}
+ public string ArrayFilter { get; set; }
+
+ ///
+ /// Specifies whether the update operation performs an
+ /// upsert operation if no documents match the query filter.
+ ///
+ public bool Upsert { get; set; } = false;
}
///
diff --git a/Frends.MongoDB.Update/Frends.MongoDB.Update/Frends.MongoDB.Update.csproj b/Frends.MongoDB.Update/Frends.MongoDB.Update/Frends.MongoDB.Update.csproj
index 1d16c54..ba1874a 100644
--- a/Frends.MongoDB.Update/Frends.MongoDB.Update/Frends.MongoDB.Update.csproj
+++ b/Frends.MongoDB.Update/Frends.MongoDB.Update/Frends.MongoDB.Update.csproj
@@ -2,7 +2,7 @@
net6.0
- 1.0.1
+ 2.0.0
Frends
Frends
Frends
@@ -19,33 +19,11 @@
PreserveNewest
-
- true
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- lib\MongoDB.Driver.dll
-
-
- lib\MongoDB.Driver.Core.dll
-
+
+
+
\ No newline at end of file
diff --git a/Frends.MongoDB.Update/Frends.MongoDB.Update/Update.cs b/Frends.MongoDB.Update/Frends.MongoDB.Update/Update.cs
index fe2617f..041bb05 100644
--- a/Frends.MongoDB.Update/Frends.MongoDB.Update/Update.cs
+++ b/Frends.MongoDB.Update/Frends.MongoDB.Update/Update.cs
@@ -6,6 +6,13 @@
using MongoDB.Driver;
using System.IO;
using System.Threading.Tasks;
+using UpdateOptions = MongoDB.Driver.UpdateOptions;
+using System.Runtime.Caching;
+using System.Linq;
+using System.Diagnostics.CodeAnalysis;
+using System.Net.Http;
+using System.Collections;
+using System.Collections.Generic;
namespace Frends.MongoDB.Update;
@@ -14,18 +21,21 @@ namespace Frends.MongoDB.Update;
///
public class MongoDB
{
- ///
- /// MongoDB update operation.
- /// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.MongoDB.Update)
- ///
- /// Input parameters.
- /// Connection parameters.
- /// Token generated by Frends to stop this task.
- /// Object { bool Success, long Count }
- public static async Task Update([PropertyTab] Input input, [PropertyTab] Connection connection, CancellationToken cancellationToken)
+ internal static readonly ObjectCache ClientCache = MemoryCache.Default;
+ private static readonly CacheItemPolicy _cachePolicy = new() { SlidingExpiration = TimeSpan.FromHours(1) };
+
+ ///
+ /// MongoDB update operation.
+ /// [Documentation](https://tasks.frends.com/tasks/frends-tasks/Frends.MongoDB.Update)
+ ///
+ /// Input parameters.
+ /// Connection parameters.
+ /// Token generated by Frends to stop this task.
+ /// Object { bool Success, long Count }
+ public static async Task Update([PropertyTab] Input input, [PropertyTab] Connection connection, CancellationToken cancellationToken)
{
- if (string.IsNullOrWhiteSpace(input.UpdateString))
- throw new Exception("Update string missing.");
+ if (string.IsNullOrWhiteSpace(input.UpdateString))
+ throw new ArgumentException("Update string missing.");
var collection = GetMongoCollection(connection.ConnectionString, connection.Database, connection.CollectionName);
@@ -44,7 +54,10 @@ public static async Task Update([PropertyTab] Input input, [PropertyTab]
}
case InputType.Filter:
- return new Result(true, await UpdateOperation(input, BsonDocument.Parse(input.Filter), collection, cancellationToken));
+ if (string.IsNullOrWhiteSpace(input.Filter))
+ throw new ArgumentException("Filter string missing.");
+
+ return new Result(true, await UpdateOperation(input, BsonDocument.Parse(input.Filter), collection, cancellationToken));
case InputType.Filters:
long count = 0;
@@ -64,22 +77,34 @@ public static async Task Update([PropertyTab] Input input, [PropertyTab]
private static async Task UpdateOperation(Input input, BsonDocument filter, IMongoCollection collection, CancellationToken cancellationToken)
{
- try
+ try
{
- UpdateDefinition update = input.UpdateString;
+ UpdateDefinition update = input.UpdateString;
+ var options = new UpdateOptions
+ {
+ IsUpsert = input.Upsert
+ };
- switch (input.UpdateOptions)
- {
- case Definitions.UpdateOptions.UpdateOne:
- var updateOne = await collection.UpdateOneAsync(filter, update, cancellationToken: cancellationToken);
- return updateOne.ModifiedCount;
- case Definitions.UpdateOptions.UpdateMany:
- var updateMany = await collection.UpdateManyAsync(filter, update, cancellationToken: cancellationToken);
- return updateMany.ModifiedCount;
- default:
- return 0;
- }
- }
+ if (!string.IsNullOrWhiteSpace(input.ArrayFilter))
+ {
+; options.ArrayFilters = new List
+ {
+ new BsonDocumentArrayFilterDefinition(BsonDocument.Parse(input.ArrayFilter))
+ };
+ }
+
+ switch (input.UpdateOptions)
+ {
+ case Definitions.UpdateOptions.UpdateOne:
+ var updateOne = await collection.UpdateOneAsync(filter, update, options, cancellationToken: cancellationToken);
+ return updateOne.UpsertedId != null ? 1 : updateOne.ModifiedCount;
+ case Definitions.UpdateOptions.UpdateMany:
+ var updateMany = await collection.UpdateManyAsync(filter, update, options, cancellationToken: cancellationToken);
+ return updateMany.UpsertedId != null ? 1 : updateMany.ModifiedCount;
+ default:
+ return 0;
+ }
+ }
catch (Exception ex)
{
throw new Exception($"UpdateOperation error: {ex}");
@@ -90,7 +115,7 @@ private static IMongoCollection GetMongoCollection(string connecti
{
try
{
- var dataBase = GetMongoDatabase(connectionString, database);
+ var dataBase = GetMongoDatabase(connectionString, database, collectionName);
var collection = dataBase.GetCollection(collectionName);
return collection;
}
@@ -100,17 +125,33 @@ private static IMongoCollection GetMongoCollection(string connecti
}
}
- private static IMongoDatabase GetMongoDatabase(string connectionString, string database)
+ private static IMongoDatabase GetMongoDatabase(string connectionString, string database, string collectionName)
{
- try
+ var cacheKey = GetMongoDbCacheKey(connectionString, database, collectionName);
+
+ if (ClientCache.Get(cacheKey) is IMongoDatabase mongoDatabase)
+ {
+ return mongoDatabase;
+ }
+
+ try
{
var mongoClient = new MongoClient(connectionString);
var dataBase = mongoClient.GetDatabase(database);
- return dataBase;
+
+ ClientCache.Add(cacheKey, dataBase, _cachePolicy);
+
+ return dataBase;
}
catch (Exception ex)
{
throw new Exception($"GetMongoDatabase error: {ex}");
}
}
+
+ [ExcludeFromCodeCoverage]
+ private static string GetMongoDbCacheKey(string connectionString, string database, string collectionName)
+ {
+ return $"{connectionString.GetHashCode()}:{database}:{collectionName}";
+ }
}
\ No newline at end of file
diff --git a/Frends.MongoDB.Update/Frends.MongoDB.Update/lib/MongoDB.Driver.Core.dll b/Frends.MongoDB.Update/Frends.MongoDB.Update/lib/MongoDB.Driver.Core.dll
deleted file mode 100644
index ef4f87f..0000000
Binary files a/Frends.MongoDB.Update/Frends.MongoDB.Update/lib/MongoDB.Driver.Core.dll and /dev/null differ
diff --git a/Frends.MongoDB.Update/Frends.MongoDB.Update/lib/MongoDB.Driver.dll b/Frends.MongoDB.Update/Frends.MongoDB.Update/lib/MongoDB.Driver.dll
deleted file mode 100644
index a5f429a..0000000
Binary files a/Frends.MongoDB.Update/Frends.MongoDB.Update/lib/MongoDB.Driver.dll and /dev/null differ
diff --git a/Frends.MongoDB.Update/README.md b/Frends.MongoDB.Update/README.md
index ff42118..be87785 100644
--- a/Frends.MongoDB.Update/README.md
+++ b/Frends.MongoDB.Update/README.md
@@ -8,11 +8,10 @@ Frends Task for MongoDB update operation.
# Installing
-You can install the Task via Frends UI Task View or you can find the NuGet package from the following NuGet feed https://www.myget.org/F/frends-tasks/api/v2.
+You can install the Task via Frends UI Task View or you can find the NuGet package from the following NuGet feed [NuGet Package](https://www.myget.org/F/frends-tasks/api/v2)
## Building
-
Rebuild the project
`dotnet build`
diff --git a/README.md b/README.md
index 3752696..aef31ec 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,7 @@ Frends Task for MongoDB related operations.
- [Frends.MongoDB.Query](Frends.MongoDB.Query/README.md)
- [Frends.MongoDB.Update](Frends.MongoDB.Update/README.md)
- [Frends.MongoDB.Delete](Frends.MongoDB.Delete/README.md)
+- [Frends.MongoDB.Index](Frends.MongoDB.Index/README.md)
# Contributing
When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.