Bao gồm tất cả các trường hiện có và thêm các trường mới vào tài liệu


123

Tôi muốn xác định một giai đoạn tổng hợp $ project, nơi tôi có thể hướng dẫn nó thêm một trường mới và bao gồm tất cả các trường hiện có mà không cần phải liệt kê tất cả các trường hiện có.

Tài liệu của tôi trông giống như sau, với nhiều trường:

{
    obj: {
        obj_field1: "hi",
        obj_field2: "hi2"
    },
    field1: "a",
    field2: "b",
    ...
    field26: "z"
}

Tôi muốn thực hiện một hoạt động tổng hợp như sau:

[
    {
        $project: {
            custom_field: "$obj.obj_field1",
            //the next part is that I don't want to do
            field1: 1,
            field2: 1,
            ...
            field26: 1
        }
    },
    ... //group, match, and whatever...
]

Có cái gì đó giống như từ khóa "bao gồm tất cả các trường" mà tôi có thể sử dụng trong trường hợp này hoặc một số cách khác để tránh phải liệt kê từng trường riêng biệt không?


1
Tính năng này sẽ có trong bản phát hành chính tiếp theo 2.6. Bạn có thể thử nó trên nhánh nhà phát triển không ổn định - sử dụng "$$ ROOT" để tham chiếu đến toàn bộ tài liệu đến. Xem chi tiết trong vé này: jira.mongodb.org/browse/SERVER-5916
Asya Kamsky

1
Vấn đề này cũng được nêu ra tại stackoverflow.com/questions/20497499/… , với một số câu trả lời hữu ích và khác.
Vince Bowdren

Câu trả lời:


168

Trong 4.2+, bạn có thể sử dụng $settoán tử đường ống tổng hợp không có gì khác ngoài bí danh để $addFieldsthêm vào 3.4

Các $addFieldsgiai đoạn tương đương với một $projectgiai đoạn mà xác định một cách rõ ràng tất cả các lĩnh vực đang tồn tại trong các tài liệu đầu vào và cho biết thêm các trường mới.

db.collection.aggregate([
    { "$addFields": { "custom_field": "$obj.obj_field1" } }
])

2
Bất kỳ ý tưởng làm thế nào để sử dụng nó trong trình điều khiển C #? dường như nó không tồn tại
Sao Homam

Tôi không quen thuộc với người lái xe C # nhưng $addFieldslà mới trong MongoDB 3.4 được hỗ trợ bởi các trình điều khiển phiên bản C # 2.5+
styvane

Tôi đã được tìm kiếm một cách để làm điều này trong C # lái xe, và cho đến nay có vẻ như cách để làm điều đó sẽ được sử dụng một cái gì đó giống nhưIAggregateFluent<TResult>.AppendStage(new JsonPipelineStageDefinition<TInput, TOutput>("{ $addFields : { myField: 'myValue' }}")
sboisse

4
Tôi phát hiện ra rằng nó thậm chí có thể thay thế một lĩnh vực nếu bạn chỉ định tên trường cùng
CME64

79

Bạn có thể sử dụng $$ ROOT để tham chiếu đến tài liệu gốc. Giữ tất cả các trường của tài liệu này trong một trường và cố gắng lấy nó sau đó (tùy thuộc vào hệ thống máy khách của bạn: Java, C ++, ...)

 [
    {
        $project: {
            custom_field: "$obj.obj_field1",
            document: "$$ROOT"

        }
    },
    ... //group, match, and whatever...
]

17
Nhưng điều này sẽ tạo ra một doc nhúng gọi là documentmột tùy chọn để tạo ra một sáp nhập doc sẽ được đẹp hơn ...
Alexander Suraphel

2
Có ai biết giải pháp để chuyển qua tất cả các cặp giá trị khóa mà không cần tạo tài liệu nhúng không?
ugotchi

11
Giữ hơi thở của bạn. MongoDB 3.4 sẽ đi kèm với giai đoạn tổng hợp $ addFields thực hiện điều này. Xem stackoverflow.com/a/24557029/4653485 .
Jérôme

Đây có vẻ là giải pháp tốt nhất hiện tại, vì bạn có thể (ít nhất là trong JS) sau đó sử dụng toán tử spread để xây dựng lại đối tượng ban đầu của bạn với custom_fieldtệp đính kèm mới . const newObj = { ...result.document, custom_field: result.custom_field }
ffritz

7

>>> Có một cái gì đó như từ khóa "bao gồm tất cả các trường" mà tôi có thể sử dụng trong trường hợp này hoặc một số giải pháp khác?

Rất tiếc, không có toán tử nào để "bao gồm tất cả các trường" trong hoạt động tổng hợp. Lý do duy nhất, tại sao, vì tập hợp chủ yếu được tạo để nhóm / tính toán dữ liệu từ các trường thu thập (tổng, trung bình, v.v.) và trả về tất cả các trường của tập hợp không phải là mục đích trực tiếp.


... bởi vì tổng hợp chủ yếu được tạo để nhóm / tính toán dữ liệu từ các trường thu thập ... Câu trả lời hay nhất trên thực tế!
felipsmartins

1
bạn có một bộ sưu tập postsvới các trường _id, title, body, like. Trường thích là một mảng _ người dùng thích bài đăng. Làm thế nào bạn có thể liệt kê tất cả các bài đăng với tất cả _id, title, body, likeCount? Trả lại tất cả các trường là mục đích trực tiếp trong trường hợp này.
doc_id

3

Kể từ phiên bản 2.6.4, Mongo DB không có tính năng như vậy cho $projectđường ống tổng hợp. Từ các tài liệu cho $project:

Chuyển các tài liệu chỉ có các trường được chỉ định sang giai đoạn tiếp theo trong đường dẫn. Các trường được chỉ định có thể là các trường hiện có từ tài liệu đầu vào hoặc các trường mới được tính toán.

Trường _id, theo mặc định, được bao gồm trong các tài liệu đầu ra. Để đưa các trường khác từ tài liệu đầu vào vào tài liệu đầu ra, bạn phải chỉ định rõ ràng việc đưa vào $ project.


2

Để thêm các trường mới vào tài liệu của bạn, bạn có thể sử dụng $addFields

từ tài liệu

và đối với tất cả các trường trong tài liệu của bạn, bạn có thể sử dụng $$ROOT

db.collection.aggregate([

{ "$addFields": { "custom_field": "$obj.obj_field1" } },
{ "$group": {
        _id : "$field1",
        data: { $push : "$$ROOT" }
    }}
])

0

theo @Deka trả lời, đối với trình điều khiển c # mongodb 2.5, bạn có thể lấy tài liệu được nhóm với tất cả các phím như bên dưới;

var group = new BsonDocument
{
 { "_id", "$groupField" },
 { "_document", new BsonDocument { { "$first", "$$ROOT" } } }
};

ProjectionDefinition<BsonDocument> projection = new BsonDocument{{ "document", "$_document"}};
var result = await col.Aggregate().Group(group).Project(projection).ToListAsync();

// For demo first record 
var fistItemAsT = BsonSerializer.Deserialize<T>(result.ToArray()[0]["document"].AsBsonDocument);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.