-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
156 lines (133 loc) · 6.16 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Microsoft.Extensions.Configuration;
namespace CosmoDBCollectionPropertyUpdater
{
static class CosmoDbCollectionPropertyUpdater
{
static async Task Main()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", true, true);
IConfigurationRoot configuration = builder.Build();
IDocumentClient client = new DocumentClient(
new Uri(configuration["CosmoDbUri"]),
configuration["CosmoDbToken"]);
CollectionProperties existingCollection = new CollectionProperties();
configuration.GetSection("CollectionProperties").Bind(existingCollection);
string newCollectionName = existingCollection.CollectionName + configuration.GetValue("TempDatabasePrefix","_");
CollectionProperties newCollection = new CollectionProperties(existingCollection) {CollectionName = newCollectionName};
try
{
Console.WriteLine($"Creating temp collection: {newCollectionName}");
await CreateCollectionAsync(client, newCollection);
Console.WriteLine("Copying documents from existing collection");
try
{
await CopyCollectionsDocumentsAsync(
client,
existingCollection,
newCollection,
configuration.GetValue("SkipDuplicates",false));
}
catch (Exception ex)
{
Console.WriteLine($"There was an error copying documents, reverting the operation {ex}");
throw;
}
Console.WriteLine("Restoring collection");
if (configuration.GetValue("DeleteOriginal", true))
{
await DeleteCollectionAsync(client, existingCollection);
await CreateCollectionAsync(client, existingCollection);
await CopyCollectionsDocumentsAsync(client, newCollection, existingCollection);
}
}
catch (Exception ex)
{
Console.WriteLine($"There has been an error {ex.InnerException}");
}
finally
{
Console.WriteLine("Removing temp collection");
await DeleteCollectionAsync(client, newCollection);
}
Console.WriteLine("Done");
Console.WriteLine("Press any key to exit..");
Console.ReadLine();
}
private static async Task CreateCollectionAsync(IDocumentClient client, CollectionProperties properties)
{
var newCollection = new DocumentCollection
{
Id = properties.CollectionName,
DefaultTimeToLive = -1,
IndexingPolicy = new IndexingPolicy(
new RangeIndex(DataType.String) { Precision = -1 },
new RangeIndex(DataType.Number) { Precision = -1 }
)
};
if (properties.PartitionKeys.Any())
{
newCollection.PartitionKey.Paths = new Collection<string>(properties.PartitionKeys);
}
if (!string.IsNullOrEmpty(properties.ExcludedPaths))
{
newCollection.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath{ Path = properties.ExcludedPaths });
}
if (properties.UniqueKeys.Any())
{
newCollection.UniqueKeyPolicy.UniqueKeys.Add(new UniqueKey { Paths = new Collection<string>(properties.UniqueKeys) });
}
await client.CreateDocumentCollectionAsync(
UriFactory.CreateDatabaseUri(properties.DatabaseName),
newCollection,
new RequestOptions { OfferThroughput = properties.OfferThroughput });
}
private static async Task CopyCollectionsDocumentsAsync(IDocumentClient client, CollectionProperties collection1, CollectionProperties collection2, bool skipDuplicates = false)
{
var collection1Uri = UriFactory.CreateDocumentCollectionUri(collection1.DatabaseName, collection1.CollectionName);
var collection2Uri = UriFactory.CreateDocumentCollectionUri(collection2.DatabaseName, collection2.CollectionName);
var documents = client.CreateDocumentQuery<Document>(collection1Uri)
.AsEnumerable().ToList();
foreach (var document in documents)
{
try
{
await client.UpsertDocumentAsync(collection2Uri, document);
}
catch (DocumentClientException ex)
{
Console.WriteLine("Found a duplicate");
if (!skipDuplicates)
{
throw;
}
}
}
var documents2 = client.CreateDocumentQuery<Document>(collection2Uri)
.AsEnumerable().ToList();
if(documents.Count != documents2.Count)
{
Console.WriteLine($"There was a mismatch the original collection has {documents.Count} documents while the new one has {documents2.Count}");
Console.WriteLine("Press c to cancel or other key to continue");
var key = Console.ReadKey();
if (key.KeyChar == 'c')
{
throw new Exception();
}
}
}
private static async Task DeleteCollectionAsync(IDocumentClient client, CollectionProperties collection)
{
var collectionUri = UriFactory.CreateDocumentCollectionUri(collection.DatabaseName, collection.CollectionName);
await client.DeleteDocumentCollectionAsync(collectionUri);
}
}
}