C# MongoDb: соответствие совпадений на поле - PullRequest
0 голосов
/ 29 марта 2020

Итак, у меня есть список объектов, некоторые будут существовать в понедельник go, а некоторые - нет.

  • Для существующих объектов я хочу обновить 1 поле
  • Для тех, которые не существуют, вставьте объект полной страницы.

Я хочу найти их через их URL. Есть ли в любом случае, чтобы сделать это?

var webapges = new List<WriteModel<Page>>();
var filterDefinition = Builders<Page>.Filter.Eq(p => p.url, **Object.url**);
var updateDefinition = Builders<Page>.Update.Set(p => p.pop, p.pop + **Object.pop??**);
listWrites.Add(new UpdateOneModel<Page>(filterDefinition, updateDefinition));
await userCollection.BulkWriteAsync(listWrites);


public class Page
    {
        [BsonId] public ObjectId Id { get; set; }
        [BsonElement("url")] public string Url { get; set; }
        [BsonElement("level")] public int Level { get; set; }
        [BsonElement("languages")] public string Languages { get; set; }
        [BsonElement("proc")] public int Proc { get; set; }
        [BsonElement("domain")] public string Domain { get; set; }
        [BsonElement("len")] public int Len { get; set; }
        [BsonElement("html")] public string Html { get; set; }
        [BsonElement("body")] public string Body { get; set; }
        [BsonElement("title")] public string Title { get; set; }
        [BsonElement("meta")] public string Meta { get; set; }
        [BsonElement("scan_date")] public BsonDateTime ScanDate { get; set; }
        [BsonElement("pop")] public int Popularity { get; set; }
}

1 Ответ

1 голос
/ 29 марта 2020

Как сказал Джо в комментариях, вы можете сделать каждое обновление Upset, это свойство на UpdateOneModel<T>, тогда вам нужно будет установить каждое свойство, которое вы хотите установить на вставке, с помощью оператора обновления $ setOnInsert.

Итак, начнем с настройки базы данных fre sh с некоторыми данными, с которыми можно поиграть:

var client = new MongoClient();
var database = client.GetDatabase("test");
await client.DropDatabaseAsync(database.DatabaseNamespace.DatabaseName);
var collection = database.GetCollection<Page>("collection1");

// Create our mix of pages
var pages = new List<Page>
{
    new Page {Url = "https://some-url/1", Body = "body1", Popularity = 0, ScanDate = DateTime.UtcNow},
    new Page {Url = "https://some-url/2", Body = "body1", Popularity = 0, ScanDate = DateTime.UtcNow},
    new Page {Url = "https://some-url/3", Body = "body1", Popularity = 0, ScanDate = DateTime.UtcNow}
};

// Insert the middle one.
await collection.InsertOneAsync(pages[1]);

Debugger.Break();

Теперь, если мы заглянем в оболочку и увидим наши данные, мы в коллекции будет одна страница, которую мы хотим обновить.

> use test
switched to db test
> show collections
collection1
> db.collection1.find().pretty()
{
        "_id" : ObjectId("5e80824b0664ae4020ee68b3"),
        "url" : "https://some-url/2",
        "level" : 0,
        "languages" : null,
        "proc" : 0,
        "domain" : null,
        "len" : 0,
        "html" : null,
        "body" : "body1",
        "title" : null,
        "meta" : null,
        "scan_date" : ISODate("2020-03-29T11:11:07.700Z"),
        "pop" : 0
}

Давайте теперь обновим все свойства популярности на наших страницах до 100, чтобы увидеть изменение.

// Update all popularity to 100
pages.ForEach(x => x.Popularity = 100);

Затем мы можем использовать немного LINQ для создания обновленных моделей, которые мы отправим в пакетную запись.

// Create all the updates as a batch
var updateOneModels = pages.Select(x =>
{
    var filterDefinition = Builders<Page>.Filter.Eq(p => p.Url, x.Url);
    var updateDefinition = Builders<Page>.Update.Set(p => p.Popularity, x.Popularity)
        .SetOnInsert(p => p.Level, x.Level)
        .SetOnInsert(p => p.Languages, x.Languages)
        .SetOnInsert(p => p.Proc, x.Proc)
        .SetOnInsert(p => p.Domain, x.Domain)
        .SetOnInsert(p => p.Len, x.Len)
        .SetOnInsert(p => p.Html, x.Html)
        .SetOnInsert(p => p.Body, x.Body)
        .SetOnInsert(p => p.Title, x.Title)
        .SetOnInsert(p => p.Meta, x.Meta)
        .SetOnInsert(p => p.ScanDate, x.ScanDate);

    return new UpdateOneModel<Page>(filterDefinition, updateDefinition) { IsUpsert = true };
}).ToList();

Теперь запустите пакет

// Run the batch
await collection.BulkWriteAsync(updateOneModels);

Теперь, если мы посмотрим на данные из оболочки, наша средняя страница была обновлена ​​и все остальное было вставлено

> db.collection1.find().pretty()
{
        "_id" : ObjectId("5e80824b0664ae4020ee68b3"),
        "url" : "https://some-url/2",
        "level" : 0,
        "languages" : null,
        "proc" : 0,
        "domain" : null,
        "len" : 0,
        "html" : null,
        "body" : "body1",
        "title" : null,
        "meta" : null,
        "scan_date" : ISODate("2020-03-29T11:11:07.700Z"),
        "pop" : 100
}
{
        "_id" : ObjectId("5e80825cc38a0ff23e1eb326"),
        "url" : "https://some-url/1",
        "body" : "body1",
        "domain" : null,
        "html" : null,
        "languages" : null,
        "len" : 0,
        "level" : 0,
        "meta" : null,
        "pop" : 100,
        "proc" : 0,
        "scan_date" : ISODate("2020-03-29T11:11:07.699Z"),
        "title" : null
}
{
        "_id" : ObjectId("5e80825cc38a0ff23e1eb327"),
        "url" : "https://some-url/3",
        "body" : "body1",
        "domain" : null,
        "html" : null,
        "languages" : null,
        "len" : 0,
        "level" : 0,
        "meta" : null,
        "pop" : 100,
        "proc" : 0,
        "scan_date" : ISODate("2020-03-29T11:11:07.700Z"),
        "title" : null
}
...