pymongo的聚合操作


pymongo的聚合操作

數據類型樣式

/* 1 */
{
    "_id" : ObjectId("5e5a32fe2a89d7c2fc05b9fc"),
    "user_id" : "1",
    "amount" : 500,
    "status" : "A"
}

/* 2 */
{
    "_id" : ObjectId("5e5a33092a89d7c2fc05ba07"),
    "user_id" : "1",
    "amount" : 250,
    "status" : "A"
}

/* 3 */
{
    "_id" : ObjectId("5e5a33152a89d7c2fc05ba13"),
    "user_id" : "2",
    "amount" : 200,
    "status" : "A"
}

/* 4 */
{
    "_id" : ObjectId("5e5a33262a89d7c2fc05ba1c"),
    "user_id" : "1",
    "amount" : 300,
    "status" : "B"
}

 

$match:過濾數據,返回符合條件的數據 

    def aggregate(self):
        match_dict = {"$match":{"status":"A"}}
        result = self.db["test_info"].aggregate([match_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)



<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FF1648>
{'_id': ObjectId('5e5a32fe2a89d7c2fc05b9fc'), 'user_id': '1', 'amount': 500, 'status': 'A'}
{'_id': ObjectId('5e5a33092a89d7c2fc05ba07'), 'user_id': '1', 'amount': 250, 'status': 'A'}
{'_id': ObjectId('5e5a33152a89d7c2fc05ba13'), 'user_id': '2', 'amount': 200, 'status': 'A'}

 

$group:將過濾后的數據進行分組 

    def aggregate_match_group(self):
        match_dict = {"$match": {"status": "A"}}
        group_dict = {"$group":{"_id":"$user_id"}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FEF708>
{'_id': '2'}
{'_id': '1'}

 

# 注意: {"$group":{"_id":"$user_id"}}  分組的名稱必須是_id才行換成其他key或者自己重新命名key報錯:pymongo.errors.OperationFailure: The field 'user_id' must be an accumulator object

分組后,我們要求,每組的amount的總和是多少?

    def aggregate_match_group(self):
        match_dict = {"$match": {"status": "A"}}
        group_dict = {"$group":{"_id":"$user_id","amount_total":{"$sum":"$amount"}}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)



<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FECD48>
{'_id': '2', 'amount_total': 200}
{'_id': '1', 'amount_total': 750}

 

# 注意:雖然分了兩組,但是其實第二組,包含了兩個內容

怎么才能顯示,每個里面成員的數量呢?

    def aggregate_match_group(self):
        match_dict = {"$match": {"status": "A"}}
        group_dict = {"$group":{"_id":"$user_id","part_quantity":{"$sum":1}}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FF0E08>
{'_id': '2', 'part_quantity': 1}
{'_id': '1', 'part_quantity': 2}

 

# 注意: {"$sum":1} 表示組內有一個,按照1遞增, {"$sum":2}  就變成了 {'_id': '1', 'part_quantity': 4} 也就是按照2遞增!

如果我們想知道整個文檔里面符合$match過濾條件的文檔有多少個呢?

    def aggregate_match_group(self):
        match_dict = {"$match": {"status": "A"}}
        group_dict = {"$group":{"_id":None,"part_quantity":{"$sum":1}}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)

<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FEBFC8>
{'_id': None, 'part_quantity': 3}

 

如果想知道整個collection里面有多少個文檔呢?

    def aggregate_match_group(self):
        match_dict = {"$match": {}}
        group_dict = {"$group":{"_id":None,"part_quantity":{"$sum":1}}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FF1D48>
{'_id': None, 'part_quantity': 4}

 

將$match過濾條件設置為{ },就可以作用於整個collection,$group分組條件"_id":None,表示文檔不分組,也就是整個文檔是一組!

/* 1 */
{
    "_id" : ObjectId("5e5a41b22a89d7c2fc05c1c5"),
    "user_id" : "1",
    "name" : "科比",
    "hometown" : "費城",
    "age" : "100",
    "gender" : ""
}

/* 2 */
{
    "_id" : ObjectId("5e5a41db2a89d7c2fc05c1dc"),
    "user_id" : "2",
    "name" : "納什",
    "hometown" : "加拿大",
    "age" : "100",
    "gender" : ""
}

/* 3 */
{
    "_id" : ObjectId("5e5a42022a89d7c2fc05c1f1"),
    "user_id" : "3",
    "name" : "蔡徐坤",
    "hometown" : "不詳",
    "age" : "100",
    "gender" : ""
}

/* 4 */
{
    "_id" : ObjectId("5e5a42252a89d7c2fc05c204"),
    "user_id" : "4",
    "name" : "gigi",
    "hometown" : "洛杉磯",
    "age" : "100",
    "gender" : ""
}

 

 

怎么獲取不同性別的人的所有user_id呢?

    def aggregate_match_group(self):
        match_dict = {"$match": {}}
        group_dict = {"$group":{"_id":"$gender","user_id":{"$push":"$user_id"}}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


{'_id': '', 'user_id': ['3', '4']}
{'_id': '', 'user_id': ['1', '2']}

 

# 注意:$push:將結果追加到列表中

 def aggregate_match_group(self):
        match_dict = {"$match": {}}
        group_dict = {"$group":{"_id":"$gender","user_id":{"$push":"$$ROOT"}}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FF0DC8>
{'_id': '', 'user_id': [{'_id': ObjectId('5e5a42022a89d7c2fc05c1f1'), 'user_id': '3', 'name': '蔡徐坤', 'hometown': '不詳', 'age': '100', 'gender': ''}, {'_id': ObjectId('5e5a42252a89d7c2fc05c204'), 'user_id': '4', 'name': 'gigi', 'hometown': '洛杉磯', 'age': '100', 'gender': ''}]}
{'_id': '', 'user_id': [{'_id': ObjectId('5e5a41b22a89d7c2fc05c1c5'), 'user_id': '1', 'name': '科比', 'hometown': '費城', 'age': '100', 'gender': ''}, {'_id': ObjectId('5e5a41db2a89d7c2fc05c1dc'), 'user_id': '2', 'name': '納什', 'hometown': '加拿大', 'age': '100', 'gender': ''}]}

 

# $$sort將整個文檔放入列表中

$gorup分組條件的 "_id" 多條件分組

    def aggregate_match_group(self):
        match_dict = {"$match": {}}
        group_dict = {"$group":{"_id":{"user_id":"$user_id","name":"$name","hometown":"$hometown","age":"$age","gender":"$gender"}}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


{'_id': {'user_id': '4', 'name': 'gigi', 'hometown': '洛杉磯', 'age': '100', 'gender': ''}}
{'_id': {'user_id': '3', 'name': '蔡徐坤', 'hometown': '不詳', 'age': '100', 'gender': ''}}
{'_id': {'user_id': '2', 'name': '納什', 'hometown': '加拿大', 'age': '100', 'gender': ''}}
{'_id': {'user_id': '1', 'name': '科比', 'hometown': '費城', 'age': '100', 'gender': ''}}

 

   def aggregate_match_group(self):
        match_dict = {"$match": {}}
        group_dict = {"$group":{"_id":{"name":"$name","age":"$age","gender":"$gender"}}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)



<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002D4EE48>
{'_id': {'name': 'gigi', 'age': '100', 'gender': ''}}
{'_id': {'name': '蔡徐坤', 'age': '100', 'gender': ''}}
{'_id': {'name': '納什', 'age': '100', 'gender': ''}}
{'_id': {'name': '科比', 'age': '100', 'gender': ''}}

 

多條件分組,並統計數量

    def aggregate_match_group(self):
        match_dict = {"$match": {}}
        group_dict = {"$group":{"_id":{"年齡":"$age","性別":"$gender"},"人數":{"$sum":1}}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FECD88>
{'_id': {'年齡': '100', '性別': ''}, '人數': 2}
{'_id': {'年齡': '100', '性別': ''}, '人數': 2}

 

對查詢數據進行修改

/* 1 */
{
    "_id" : ObjectId("5e5a41b22a89d7c2fc05c1c5"),
    "user_id" : "1",
    "name" : "科比",
    "hometown" : "費城",
    "age" : "42",
    "gender" : ""
}

/* 2 */
{
    "_id" : ObjectId("5e5a41db2a89d7c2fc05c1dc"),
    "user_id" : "2",
    "name" : "納什",
    "hometown" : "加拿大",
    "age" : "40",
    "gender" : ""
}

/* 3 */
{
    "_id" : ObjectId("5e5a42022a89d7c2fc05c1f1"),
    "user_id" : "3",
    "name" : "蔡徐坤",
    "hometown" : "不詳",
    "age" : "3",
    "gender" : ""
}

/* 4 */
{
    "_id" : ObjectId("5e5a42252a89d7c2fc05c204"),
    "user_id" : "4",
    "name" : "gigi",
    "hometown" : "洛杉磯",
    "age" : "14",
    "gender" : ""
}

 

獲取年齡年齡大於3歲的信息

$match

    def aggregate_match_group(self):
        match_dict = {"$match":{"age":{"$gt":"3"}}}
        result = self.db["test_info"].aggregate([match_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)

<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FF1C48>
{'_id': ObjectId('5e5a41b22a89d7c2fc05c1c5'), 'user_id': '1', 'name': '科比', 'hometown': '費城', 'age': '42', 'gender': ''}
{'_id': ObjectId('5e5a41db2a89d7c2fc05c1dc'), 'user_id': '2', 'name': '納什', 'hometown': '加拿大', 'age': '40', 'gender': ''}

 

# 查詢錯誤:gigi的年齡也是大於3,不顯示,我們將數據里面的年齡類型從str換成int類型,繼續查看

    def aggregate_match_group(self):
        match_dict = {"$match":{"age":{"$gt":3}}}
        result = self.db["test_info"].aggregate([match_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FF1C88>
{'_id': ObjectId('5e5a41b22a89d7c2fc05c1c5'), 'user_id': '1', 'name': '科比', 'hometown': '費城', 'age': 42, 'gender': ''}
{'_id': ObjectId('5e5a41db2a89d7c2fc05c1dc'), 'user_id': '2', 'name': '納什', 'hometown': '加拿大', 'age': 40, 'gender': ''}
{'_id': ObjectId('5e5a42252a89d7c2fc05c204'), 'user_id': '4', 'name': 'gigi', 'hometown': '洛杉磯', 'age': 14, 'gender': ''}

 

# 查詢正確:因此當進行比較值的操作,注意字段類型必須是int類型

獲取年齡大於3歲,不同性別的人數

 def aggregate_match_group(self):
        match_dict = {"$match":{"age":{"$gt":3}}}
        group_dict = {"$group":{"_id":"$gender","數量":{"$sum":1}}}
        result = self.db["test_info"].aggregate([match_dict,group_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FF1C88>
{'_id': '', '數量': 1}
{'_id': '', '數量': 2}

 

$preject類型與find里面的limit,需要顯示的設置為1,不顯示的設置為0

    def aggregate_project(self):
        project_dict = {"$project":{"_id":0,"name":1,"hometown":1}}
        result = self.db["test_info"].aggregate([project_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FE9F88>
{'name': '科比', 'hometown': '費城'}
{'name': '納什', 'hometown': '加拿大'}
{'name': '蔡徐坤', 'hometown': '不詳'}
{'name': 'gigi', 'hometown': '洛杉磯'}

 

 

# 注意:其他字段沒有賦值1就不顯示,但是_id字段除外,不設置,默認顯示

    def aggregate_project(self):
        group_dict = {"$group":{"_id":"$gender","quantity":{"$sum":1}}}
        project_dict = {"$project":{"_id":1,"quantity":1}}
        result = self.db["test_info"].aggregate([group_dict,project_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


{'_id': '', 'quantity': 2}
{'_id': '', 'quantity': 2}

 

$sort:排序命令

年齡從小到大返回排序好的數據

  def aggregate_sort(self):
        sort_dict = {"$sort":{"age":1}}
        result = self.db["test_info"].aggregate([sort_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000003012148>
{'_id': ObjectId('5e5a42022a89d7c2fc05c1f1'), 'user_id': '3', 'name': '蔡徐坤', 'hometown': '不詳', 'age': 3, 'gender': ''}
{'_id': ObjectId('5e5a42252a89d7c2fc05c204'), 'user_id': '4', 'name': 'gigi', 'hometown': '洛杉磯', 'age': 14, 'gender': ''}
{'_id': ObjectId('5e5a41db2a89d7c2fc05c1dc'), 'user_id': '2', 'name': '納什', 'hometown': '加拿大', 'age': 40, 'gender': ''}
{'_id': ObjectId('5e5a41b22a89d7c2fc05c1c5'), 'user_id': '1', 'name': '科比', 'hometown': '費城', 'age': 42, 'gender': ''}

 

年齡從大到小返回排序好的數據

    def aggregate_sort(self):
        sort_dict = {"$sort":{"age":-1}}
        result = self.db["test_info"].aggregate([sort_dict])
        print(type(result))
        print(result)
        for i in result:
            print(i)


<class 'pymongo.command_cursor.CommandCursor'>
<pymongo.command_cursor.CommandCursor object at 0x0000000002FE5F88>
{'_id': ObjectId('5e5a41b22a89d7c2fc05c1c5'), 'user_id': '1', 'name': '科比', 'hometown': '費城', 'age': 42, 'gender': ''}
{'_id': ObjectId('5e5a41db2a89d7c2fc05c1dc'), 'user_id': '2', 'name': '納什', 'hometown': '加拿大', 'age': 40, 'gender': ''}
{'_id': ObjectId('5e5a42252a89d7c2fc05c204'), 'user_id': '4', 'name': 'gigi', 'hometown': '洛杉磯', 'age': 14, 'gender': ''}
{'_id': ObjectId('5e5a42022a89d7c2fc05c1f1'), 'user_id': '3', 'name': '蔡徐坤', 'hometown': '不詳', 'age': 3, 'gender': ''}

 

數據類型

/* 10 */
{
    "_id" : ObjectId("5e58c4102a89d7c2fc051ba4"),
    "vaccine_name" : "破傷風",
    "vaccine_id" : "2",
    "user_id" : "110",
    "farm_id" : "110",
    "fold_id" : "110",
    "farm_name" : "110牧場",
    "fold_name" : "110圈舍",
    "animal_number" : "133",
    "equipment_number" : "133",
    "type" : "goat",
    "inject_quantity" : "100",
    "vaccine_time" : ISODate("2020-06-15T15:45:22.000Z"),
    "is_delete" : "0"
}

/* 11 */
{
    "_id" : ObjectId("5e5a510d2a89d7c2fc05cac7"),
    "vaccine_name" : "破傷風",
    "vaccine_id" : "2",
    "user_id" : "110",
    "farm_id" : "110",
    "fold_id" : "110",
    "farm_name" : "110牧場",
    "fold_name" : "110圈舍",
    "animal_number" : "133",
    "equipment_number" : "133",
    "type" : "goat",
    "inject_quantity" : "100",
    "vaccine_time" : ISODate("2020-07-15T15:45:22.000Z"),
    "is_delete" : "0"
}

/* 12 */
{
    "_id" : ObjectId("5e5a511b2a89d7c2fc05cad2"),
    "vaccine_name" : "破傷風",
    "vaccine_id" : "2",
    "user_id" : "110",
    "farm_id" : "110",
    "fold_id" : "110",
    "farm_name" : "110牧場",
    "fold_name" : "110圈舍",
    "animal_number" : "133",
    "equipment_number" : "133",
    "type" : "goat",
    "inject_quantity" : "100",
    "vaccine_time" : ISODate("2020-08-15T15:45:22.000Z"),
    "is_delete" : "0"
}

/* 13 */
{
    "_id" : ObjectId("5e5a51282a89d7c2fc05cada"),
    "vaccine_name" : "破傷風",
    "vaccine_id" : "2",
    "user_id" : "110",
    "farm_id" : "110",
    "fold_id" : "110",
    "farm_name" : "110牧場",
    "fold_name" : "110圈舍",
    "animal_number" : "133",
    "equipment_number" : "133",
    "type" : "goat",
    "inject_quantity" : "100",
    "vaccine_time" : ISODate("2020-10-15T15:45:22.000Z"),
    "is_delete" : "0"
}

/* 14 */
{
    "_id" : ObjectId("5e5a51422a89d7c2fc05caec"),
    "vaccine_name" : "破傷風",
    "vaccine_id" : "2",
    "user_id" : "110",
    "farm_id" : "110",
    "fold_id" : "110",
    "farm_name" : "110牧場",
    "fold_name" : "110圈舍",
    "animal_number" : "133",
    "equipment_number" : "133",
    "type" : "goat",
    "inject_quantity" : "100",
    "vaccine_time" : ISODate("2020-11-15T15:45:22.000Z"),
    "is_delete" : "0"
}

/* 15 */
{
    "_id" : ObjectId("5e5a514d2a89d7c2fc05caf5"),
    "vaccine_name" : "破傷風",
    "vaccine_id" : "2",
    "user_id" : "110",
    "farm_id" : "110",
    "fold_id" : "110",
    "farm_name" : "110牧場",
    "fold_name" : "110圈舍",
    "animal_number" : "133",
    "equipment_number" : "133",
    "type" : "goat",
    "inject_quantity" : "100",
    "vaccine_time" : ISODate("2020-12-15T15:45:22.000Z"),
    "is_delete" : "0"
}

 

需求:獲取equipment_number=13,vaccine_time按照時間倒敘排列,返回數據

    def get_all_by_time_object(self,collection):
        """按照時間類型排序 vaccine_time的類型是 ISODate("2020-12-15T15:45:22.000Z")類型"""
        if self.connect_result:
            match_dict = {"$match":{"equipment_number":"133","type":"goat"}}
            sort_dict = {"$sort":{"vaccine_time":-1}}
            result = self.db[collection].aggregate([match_dict,sort_dict])
            for i in result:
                print(i)

{'_id': ObjectId('5e5a514d2a89d7c2fc05caf5'), 'vaccine_name': '破傷風', 'vaccine_id': '2', 'user_id': '110', 'farm_id': '110', 'fold_id': '110', 'farm_name': '110牧場', 'fold_name': '110圈舍', 'animal_number': '133', 'equipment_number': '133', 'type': 'goat', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 12, 15, 15, 45, 22), 'is_delete': '0'}
{'_id': ObjectId('5e5a51422a89d7c2fc05caec'), 'vaccine_name': '破傷風', 'vaccine_id': '2', 'user_id': '110', 'farm_id': '110', 'fold_id': '110', 'farm_name': '110牧場', 'fold_name': '110圈舍', 'animal_number': '133', 'equipment_number': '133', 'type': 'goat', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 11, 15, 15, 45, 22), 'is_delete': '0'}
{'_id': ObjectId('5e5a51282a89d7c2fc05cada'), 'vaccine_name': '破傷風', 'vaccine_id': '2', 'user_id': '110', 'farm_id': '110', 'fold_id': '110', 'farm_name': '110牧場', 'fold_name': '110圈舍', 'animal_number': '133', 'equipment_number': '133', 'type': 'goat', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 10, 15, 15, 45, 22), 'is_delete': '0'}
{'_id': ObjectId('5e5a511b2a89d7c2fc05cad2'), 'vaccine_name': '破傷風', 'vaccine_id': '2', 'user_id': '110', 'farm_id': '110', 'fold_id': '110', 'farm_name': '110牧場', 'fold_name': '110圈舍', 'animal_number': '133', 'equipment_number': '133', 'type': 'goat', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 8, 15, 15, 45, 22), 'is_delete': '0'}
{'_id': ObjectId('5e5a510d2a89d7c2fc05cac7'), 'vaccine_name': '破傷風', 'vaccine_id': '2', 'user_id': '110', 'farm_id': '110', 'fold_id': '110', 'farm_name': '110牧場', 'fold_name': '110圈舍', 'animal_number': '133', 'equipment_number': '133', 'type': 'goat', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 7, 15, 15, 45, 22), 'is_delete': '0'}
{'_id': ObjectId('5e58c4102a89d7c2fc051ba4'), 'vaccine_name': '破傷風', 'vaccine_id': '2', 'user_id': '110', 'farm_id': '110', 'fold_id': '110', 'farm_name': '110牧場', 'fold_name': '110圈舍', 'animal_number': '133', 'equipment_number': '133', 'type': 'goat', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 6, 15, 15, 45, 22), 'is_delete': '0'}

 

過濾掉一些字段,選擇性顯示需要的字段

    def get_all_by_time_object(self,collection):
        """按照時間類型排序 vaccine_time的類型是 ISODate("2020-12-15T15:45:22.000Z")類型"""
        if self.connect_result:
            match_dict = {"$match":{"equipment_number":"133","type":"goat"}}
            sort_dict = {"$sort":{"vaccine_time":-1}}
            project_dict = {"$project":{"_id":0,"animal_number":1,"inject_quantity":1,"vaccine_time":1,"vaccine_name":1}}
            result = self.db[collection].aggregate([match_dict,sort_dict,project_dict])
            for i in result:
                print(i)

{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 12, 15, 15, 45, 22)}
{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 11, 15, 15, 45, 22)}
{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 10, 15, 15, 45, 22)}
{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 8, 15, 15, 45, 22)}
{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 7, 15, 15, 45, 22)}
{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 6, 15, 15, 45, 22)}

 

$limit :限制返回的條數

    def get_all_by_limit(self,collection):
        if self.connect_result:
            match_dict = {"$match": {"equipment_number": "133", "type": "goat"}}
            sort_dict = {"$sort": {"vaccine_time": -1}}
            project_dict = {
                "$project": {"_id": 0, "animal_number": 1, "inject_quantity": 1, "vaccine_time": 1, "vaccine_name": 1}}
            limit_dict = {"$limit":2}
            result = self.db[collection].aggregate([match_dict, sort_dict, project_dict,limit_dict])
            for i in result:
                print(i)



{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 12, 15, 15, 45, 22)}
{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 11, 15, 15, 45, 22)}

 

$skip:跳過指定數量,返回剩余數量的內容

    def get_all_by_skip(self,collection):
        if self.connect_result:
            match_dict = {"$match": {"equipment_number": "133", "type": "goat"}}
            sort_dict = {"$sort": {"vaccine_time": -1}}
            project_dict = {
                "$project": {"_id": 0, "animal_number": 1, "inject_quantity": 1, "vaccine_time": 1, "vaccine_name": 1}}
            skip_dict = {"$skip":2}
            result = self.db[collection].aggregate([match_dict, sort_dict, project_dict,skip_dict])
            for i in result:
                print(i)



{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 10, 15, 15, 45, 22)}
{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 8, 15, 15, 45, 22)}
{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 7, 15, 15, 45, 22)}
{'vaccine_name': '破傷風', 'animal_number': '133', 'inject_quantity': '100', 'vaccine_time': datetime.datetime(2020, 6, 15, 15, 45, 22)}

 $ match過濾條件的或查詢

數據結構如下

/* 1 */
{
    "_id" : ObjectId("5e5a41b22a89d7c2fc05c1c5"),
    "user_id" : "1",
    "name" : "科比",
    "hometown" : "費城",
    "age" : 42,
    "gender" : ""
}

/* 2 */
{
    "_id" : ObjectId("5e5a41db2a89d7c2fc05c1dc"),
    "user_id" : "2",
    "name" : "納什",
    "hometown" : "加拿大",
    "age" : 40,
    "gender" : ""
}

/* 3 */
{
    "_id" : ObjectId("5e5a42022a89d7c2fc05c1f1"),
    "user_id" : "3",
    "name" : "蔡徐坤",
    "hometown" : "不詳",
    "age" : 3,
    "gender" : ""
}

/* 4 */
{
    "_id" : ObjectId("5e5a42252a89d7c2fc05c204"),
    "user_id" : "4",
    "name" : "gigi",
    "hometown" : "洛杉磯",
    "age" : 14,
    "gender" : ""
}

 

查詢年齡大於小於14歲或者大於40歲的人的信息

    def get_all_by_or_match(self,collection):
        if self.connect_result:
            match_dict = {"$match": {"$or":[{"age":{"$gt":40}},{"age":{"$lt":14}}]}}
            result = self.db[collection].aggregate([match_dict])
            for i in result:
                print(i)


{'_id': ObjectId('5e5a41b22a89d7c2fc05c1c5'), 'user_id': '1', 'name': '科比', 'hometown': '費城', 'age': 42, 'gender': ''}
{'_id': ObjectId('5e5a42022a89d7c2fc05c1f1'), 'user_id': '3', 'name': '蔡徐坤', 'hometown': '不詳', 'age': 3, 'gender': ''}

 

$ match過濾條件的范圍查詢

$gt和$lt判斷的范圍都是int類型,那么我們要查找hometown 在列表中 ["加拿大","洛杉磯 ","費城 "]的數據,應該怎么辦呢?

 

    def get_all_by_in_match(self,collection):
        if self.connect_result:
            match_dict = {"$match": {"hometown":{"$in":["加拿大","洛杉磯","費城"]}}}
            result = self.db[collection].aggregate([match_dict])
            for i in result:
                print(i)



{'_id': ObjectId('5e5a41b22a89d7c2fc05c1c5'), 'user_id': '1', 'name': '科比', 'hometown': '費城', 'age': 42, 'gender': ''}
{'_id': ObjectId('5e5a41db2a89d7c2fc05c1dc'), 'user_id': '2', 'name': '納什', 'hometown': '加拿大', 'age': 40, 'gender': ''}
{'_id': ObjectId('5e5a42252a89d7c2fc05c204'), 'user_id': '4', 'name': 'gigi', 'hometown': '洛杉磯', 'age': 14, 'gender': ''}

 

 

查詢年齡在[14,4,3]內的人的信息

    def get_all_by_in_match(self,collection):
        if self.connect_result:
            match_dict = {"$match":{"age":{"$in":[14,40,3]}}}
            result = self.db[collection].aggregate([match_dict])
            for i in result:
                print(i)


{'_id': ObjectId('5e5a41db2a89d7c2fc05c1dc'), 'user_id': '2', 'name': '納什', 'hometown': '加拿大', 'age': 40, 'gender': ''}
{'_id': ObjectId('5e5a42022a89d7c2fc05c1f1'), 'user_id': '3', 'name': '蔡徐坤', 'hometown': '不詳', 'age': 3, 'gender': ''}
{'_id': ObjectId('5e5a42252a89d7c2fc05c204'), 'user_id': '4', 'name': 'gigi', 'hometown': '洛杉磯', 'age': 14, 'gender': ''}

 

數據結構如下

/* 1 */
{
    "_id" : ObjectId("5e5b99052a89d7c2fc0653a0"),
    "farm_id" : "1",
    "animal_number" : "1",
    "milking_time" : ISODate("2020-02-01T15:45:22.000Z"),
    "milking_quantity" : 100
}

/* 2 */
{
    "_id" : ObjectId("5e5b993d2a89d7c2fc0653cf"),
    "farm_id" : "1",
    "animal_number" : "2",
    "milking_time" : ISODate("2020-02-01T18:46:33.000Z"),
    "milking_quantity" : 120
}

/* 3 */
{
    "_id" : ObjectId("5e5b996f2a89d7c2fc0653eb"),
    "farm_id" : "1",
    "animal_number" : "1",
    "milking_time" : ISODate("2020-02-02T08:45:22.000Z"),
    "milking_quantity" : 150
}

/* 4 */
{
    "_id" : ObjectId("5e5b9a042a89d7c2fc06543e"),
    "farm_id" : "1",
    "animal_number" : "2",
    "milking_time" : ISODate("2020-02-02T09:33:22.000Z"),
    "milking_quantity" : 90
}

/* 5 */
{
    "_id" : ObjectId("5e5b9a2b2a89d7c2fc065455"),
    "farm_id" : "1",
    "animal_number" : "1",
    "milking_time" : ISODate("2020-02-03T10:30:30.000Z"),
    "milking_quantity" : 98
}

/* 6 */
{
    "_id" : ObjectId("5e5b9a452a89d7c2fc065464"),
    "farm_id" : "1",
    "animal_number" : "2",
    "milking_time" : ISODate("2020-02-03T11:45:22.000Z"),
    "milking_quantity" : 110
}

 

需求:牧場1下的所有羊,每天的產奶量平均值是多少,每三天的產奶量平均值是多少?

    def get_all_by_avg_milk(self,collection):
        if self.connect_result:
            s_time = datetime(2020,2,1,00,00,00)
            e_time = datetime(2020,2,1,23,59,59)
            match_dict = {"$match": {"farm_id":"1","milking_time":{"$gte":s_time,"$lte":e_time}}}
            group_dict = {"$group":{"_id":None,"2020-2-1日產奶量平均值為":{"$avg":"$milking_quantity"}}}
            result = self.db[collection].aggregate([match_dict,group_dict])
            for i in result:
                print(i)


{'_id': None, '2020-2-1日產奶量平均值為': 110.0}

 

    def get_all_by_avg_milk(self,collection):
        if self.connect_result:
            s_time = datetime(2020,2,1,00,00,00)
            e_time = datetime(2020,2,3,23,59,59)
            match_dict = {"$match": {"farm_id":"1","milking_time":{"$gte":s_time,"$lte":e_time}}}
            group_dict = {"$group":{"_id":None,"三天產奶量平均值為":{"$avg":"$milking_quantity"}}}
            result = self.db[collection].aggregate([match_dict,group_dict])
            for i in result:
                print(i)


{'_id': None, '三天產奶量平均值為': 111.33333333333333}

 

(100 + 120 + 150 + 90 + 98 + 110 )/3 = 222.6666

mogno給的結果是 222.666/2 = 111.3333 分組后一共取出六條數據,除以6了,造成結果錯誤,怎么解決呢?

先求總產量,然后分布計算結果

    def get_all_by_avg_milk(self,collection):
        if self.connect_result:
            s_time = datetime(2020,2,1,00,00,00)
            e_time = datetime(2020,2,3,23,59,59)
            match_dict = {"$match": {"farm_id":"1","milking_time":{"$gte":s_time,"$lte":e_time}}}
            group_dict = {"$group":{"_id":None,"三天產奶量總和為":{"$sum":"$milking_quantity"}}}
            result = self.db[collection].aggregate([match_dict,group_dict])
            for i in result:
                print(i)
                print("三天產奶量的平均值是%s"%(str(i.get("三天產奶量總和為")/3)))


{'_id': None, '三天產奶量總和為': 668}
三天產奶量的平均值是222.66666666666666

 

需求:輸出2020-2-1號產奶量最低的羊的編號和最高的羊的編號

    def get_all_by_avg_milk(self,collection):
        if self.connect_result:
            s_time = datetime(2020,2,1,00,00,00)
            e_time = datetime(2020,2,1,23,59,59)
            match_dict = {"$match": {"farm_id":"1","milking_time":{"$gte":s_time,"$lte":e_time}}}
            group_dict = {"$group":{"_id":None,"max_quantity":{"$max":"$milking_quantity"}}}
            result = self.db[collection].aggregate([match_dict,group_dict])
            for i in result:
                print(i)


{'_id': None, 'max_quantity': 120}

 

max_quantity查庫獲得animal_nubmer

 

$unwind:針對文檔里面的數組進行操作

數據類型

{
    "_id" : ObjectId("5e5ccf222a89d7c2fc06e9d0"),
    "user_id" : "A",
    "data" : [ 
        {
            "city" : "beijing",
            "income" : 100000
        }, 
        {
            "city" : "shanghai",
            "income" : 150000
        }, 
        {
            "city" : "shanghai",
            "income" : 150000
        }
    ]
}

 

 

結果是:將列表中的每一個內容和外面的鍵重新組合形成一條數據

 

    def find_list(self,collection):
        unwind_dict = {"$unwind":"$data"}
        result = self.db[collection].aggregate([unwind_dict])
        print(result)
        print(type(result))
        for i in result:
            print(i)


<pymongo.command_cursor.CommandCursor object at 0x0000000002D58488>
<class 'pymongo.command_cursor.CommandCursor'>
{'_id': ObjectId('5e5ccf222a89d7c2fc06e9d0'), 'user_id': 'A', 'data': {'city': 'beijing', 'income': 100000}}
{'_id': ObjectId('5e5ccf222a89d7c2fc06e9d0'), 'user_id': 'A', 'data': {'city': 'shanghai', 'income': 150000}}
{'_id': ObjectId('5e5ccf222a89d7c2fc06e9d0'), 'user_id': 'A', 'data': {'city': 'shanghai', 'income': 150000}}

 

需求,計算A在上海收入的總和是多少?

    def find_list_for_sum(self,collection):
        match_dict1 = {"$match":{"user_id":"A"}}
        unwind_dict = {"$unwind":"$data"}
        match_dict2 = {"$match":{"data.city":"shanghai"}}
        group_dict = {"$group":{"_id":"$data.city","收入總和":{"$sum":"$data.income"}}}
        result = self.db[collection].aggregate([match_dict1,unwind_dict,match_dict2,group_dict])
        print(result)
        print(type(result))
        for i in result:
            print(i)


<pymongo.command_cursor.CommandCursor object at 0x0000000002FE9FC8>
<class 'pymongo.command_cursor.CommandCursor'>
{'_id': 'shanghai', '收入總和': 300000}

 

# 補充一下,如果是列表,怎么給列表里面添加數據,怎么給從列表里面刪除數據呢? $addToSet 和 $pull

需求:給上面的數據的data列表中添加一條數據  {"city":"shenzhen","income":30000}

    def add_to_list(self,collection):
        query_dict = dict()
        query_dict["user_id"] = "A"
        result = self.db[collection].update(query_dict,{"$addToSet":{"data":{"city":"shenzhen","income":30000}}})
        if result.get("nModified") == 1:
            print("添加成功")
            

{
    "_id" : ObjectId("5e5ccf222a89d7c2fc06e9d0"),
    "user_id" : "A",
    "data" : [ 
        {
            "city" : "beijing",
            "income" : 100000
        }, 
        {
            "city" : "shanghai",
            "income" : 150000
        }, 
        {
            "city" : "shanghai",
            "income" : 150000
        }, 
        {
            "city" : "shenzhen",
            "income" : 30000
        }
    ]
}

 

# 問題:這種天界方式:不能向data列表里面添加相同的鍵值對,連續插入{"city":"shenzhen","income":20000},並不會成功!

 

# TODO 待續

2020-3-20

需求:多個牧場下,每一個羊的飲水總數小於2的,返回其equipment_number

數據樣式:

/* 1 */
{
    "_id" : ObjectId("5e746c378fc1e7a977e6be06"),
    "farm_id" : "123",
    "farm_name" : "測試",
    "fold_id" : "123",
    "fold_name" : "測試",
    "device_number" : "123",
    "equipment_number" : "123",
    "animal_number" : "123",
    "drink_quantity" : 100,
    "type" : "goat",
    "drink_time" : ISODate("2020-03-20T15:09:43.454Z")
}

/* 2 */
{
    "_id" : ObjectId("5e746c448fc1e7a977e6be07"),
    "farm_id" : "123",
    "farm_name" : "測試",
    "fold_id" : "123",
    "fold_name" : "測試",
    "device_number" : "123",
    "equipment_number" : "123",
    "animal_number" : "123",
    "drink_quantity" : 200,
    "type" : "goat",
    "drink_time" : ISODate("2020-03-20T15:09:56.139Z")
}

/* 3 */
{
    "_id" : ObjectId("5e746c488fc1e7a977e6be08"),
    "farm_id" : "123",
    "farm_name" : "測試",
    "fold_id" : "123",
    "fold_name" : "測試",
    "device_number" : "123",
    "equipment_number" : "123",
    "animal_number" : "123",
    "drink_quantity" : 300,
    "type" : "goat",
    "drink_time" : ISODate("2020-03-20T15:10:00.115Z")
}

/* 4 */
{
    "_id" : ObjectId("5e7474b1e47b4ffc8fbd4d3b"),
    "farm_id" : "123",
    "farm_name" : "測試",
    "fold_id" : "123",
    "fold_name" : "測試",
    "device_number" : "123",
    "equipment_number" : "124",
    "animal_number" : "124",
    "drink_quantity" : 100,
    "type" : "goat",
    "drink_time" : ISODate("2020-03-20T15:45:53.727Z")
}

/* 5 */
{
    "_id" : ObjectId("5e7474b7e47b4ffc8fbd4d3c"),
    "farm_id" : "123",
    "farm_name" : "測試",
    "fold_id" : "123",
    "fold_name" : "測試",
    "device_number" : "123",
    "equipment_number" : "124",
    "animal_number" : "124",
    "drink_quantity" : 200,
    "type" : "goat",
    "drink_time" : ISODate("2020-03-20T15:45:59.674Z")
}

/* 6 */
{
    "_id" : ObjectId("5e7474c0e47b4ffc8fbd4d3d"),
    "farm_id" : "123",
    "farm_name" : "測試",
    "fold_id" : "123",
    "fold_name" : "測試",
    "device_number" : "123",
    "equipment_number" : "125",
    "animal_number" : "125",
    "drink_quantity" : 100,
    "type" : "goat",
    "drink_time" : ISODate("2020-03-20T15:46:08.953Z")
}

/* 7 */
{
    "_id" : ObjectId("5e748632217a21f9adb48c12"),
    "farm_id" : "125",
    "farm_name" : "測試",
    "fold_id" : "125",
    "fold_name" : "測試",
    "device_number" : "125",
    "equipment_number" : "125",
    "animal_number" : "125",
    "drink_quantity" : 100,
    "type" : "goat",
    "drink_time" : ISODate("2020-03-20T17:00:34.398Z")
}

 

查詢 123 125牧場下,飲水次數小於2的equipment_mumber,飲水次數就是有一條數據,就是飲水一次

    def aggregate_many(self):
        # 獲取所有牧場下,飲水次數小於2的羊的equipment_number
        match_dict = {"$match":{"farm_id":{"$in":["123","125"]}}}
        project_dict = {"$project":{"_id":0}}
        group_dict = {"$group":{"_id":{"equipment_number":"$equipment_number","farm_id":"$farm_id"},"total_count":{"$sum":1}}}
        # match_dict_1 = {"$match":{"total_count":{"$lt":2}}}
        result = self.db["sheep_water_intake"].aggregate([match_dict,project_dict,group_dict])
        for i in result:
            print(i)

{'_id': {'equipment_number': '125', 'farm_id': '125'}, 'total_count': 1}
{'_id': {'equipment_number': '125', 'farm_id': '123'}, 'total_count': 1}
{'_id': {'equipment_number': '124', 'farm_id': '123'}, 'total_count': 2}
{'_id': {'equipment_number': '123', 'farm_id': '123'}, 'total_count': 3}

 

首先考慮去重的問題,group_dict = {"$group":{"_id":{"equipment_number":"$equipment_number","farm_id":"$farm_id"},"total_count":{"$sum":1}}}

group應該是先分組,分完組之后,進行累加,先看看不分組的數據

    def aggregate_many(self):
        # 獲取所有牧場下,飲水次數小於2的羊的equipment_number
        match_dict = {"$match":{"farm_id":{"$in":["123","125"]}}}
        project_dict = {"$project":{"_id":0}}
        # group_dict = {"$group":{"_id":{"equipment_number":"$equipment_number","farm_id":"$farm_id"},"total_count":{"$sum":1}}}
        match_dict_1 = {"$match":{"total_count":{"$lt":2}}}
        result = self.db["sheep_water_intake"].aggregate([match_dict,project_dict])
        for i in result:
            print(i)



{'farm_id': '123', 'farm_name': '測試', 'fold_id': '123', 'fold_name': '測試', 'device_number': '123', 'equipment_number': '123', 'animal_number': '123', 'drink_quantity': 100, 'type': 'goat', 'drink_time': datetime.datetime(2020, 3, 20, 15, 9, 43, 454000)}
{'farm_id': '123', 'farm_name': '測試', 'fold_id': '123', 'fold_name': '測試', 'device_number': '123', 'equipment_number': '123', 'animal_number': '123', 'drink_quantity': 200, 'type': 'goat', 'drink_time': datetime.datetime(2020, 3, 20, 15, 9, 56, 139000)}
{'farm_id': '123', 'farm_name': '測試', 'fold_id': '123', 'fold_name': '測試', 'device_number': '123', 'equipment_number': '123', 'animal_number': '123', 'drink_quantity': 300, 'type': 'goat', 'drink_time': datetime.datetime(2020, 3, 20, 15, 10, 0, 115000)}
{'farm_id': '123', 'farm_name': '測試', 'fold_id': '123', 'fold_name': '測試', 'device_number': '123', 'equipment_number': '124', 'animal_number': '124', 'drink_quantity': 100, 'type': 'goat', 'drink_time': datetime.datetime(2020, 3, 20, 15, 45, 53, 727000)}
{'farm_id': '123', 'farm_name': '測試', 'fold_id': '123', 'fold_name': '測試', 'device_number': '123', 'equipment_number': '124', 'animal_number': '124', 'drink_quantity': 200, 'type': 'goat', 'drink_time': datetime.datetime(2020, 3, 20, 15, 45, 59, 674000)}
{'farm_id': '123', 'farm_name': '測試', 'fold_id': '123', 'fold_name': '測試', 'device_number': '123', 'equipment_number': '125', 'animal_number': '125', 'drink_quantity': 100, 'type': 'goat', 'drink_time': datetime.datetime(2020, 3, 20, 15, 46, 8, 953000)}
{'farm_id': '125', 'farm_name': '測試', 'fold_id': '125', 'fold_name': '測試', 'device_number': '125', 'equipment_number': '125', 'animal_number': '125', 'drink_quantity': 100, 'type': 'goat', 'drink_time': datetime.datetime(2020, 3, 20, 17, 0, 34, 398000)}

 

最終的結果

    def aggregate_many(self):
        # 獲取所有牧場下,飲水次數小於2的羊的equipment_number
        match_dict = {"$match":{"farm_id":{"$in":["123","125"]}}}
        project_dict = {"$project":{"_id":0}}
        group_dict = {"$group":{"_id":{"equipment_number":"$equipment_number","farm_id":"$farm_id"},"total_count":{"$sum":1}}}
        match_dict_1 = {"$match":{"total_count":{"$lt":2}}}
        result = self.db["sheep_water_intake"].aggregate([match_dict,project_dict,group_dict,match_dict_1])
        for i in result:
            print(i)

{'_id': {'equipment_number': '125', 'farm_id': '125'}, 'total_count': 1}
{'_id': {'equipment_number': '125', 'farm_id': '123'}, 'total_count': 1}

 

$lookup 多表聯查

test2

{
    "_id" : ObjectId("5e7c756b2a89d7c2fc178f57"),
    "brand" : "惠普公司",
    "address" : "美國"
}

 

test1

{
    "_id" : ObjectId("5e7c753b2a89d7c2fc178f38"),
    "name" : "暗夜精靈筆記本電腦",
    "brand_id" : "5e7c756b2a89d7c2fc178f57",

} { "_id" : ObjectId("5e7c75d02a89d7c2fc178fb0"), "name" : "暗夜精靈2", "brand_id" : "5e7c756b2a89d7c2fc178f57", "price" : 5600 }

 

通過test2的_id獲取所有brand_id為_id的電腦名稱和價格

from pymongo import MongoClient
class PyMongoTest(object):

    def __init__(self):
        self.host = "xx"
        self.port = xx
        self.username = "xx"
        self.password = "xx"
        self.database = "xx"
        self.client = MongoClient(host=self.host,port=self.port)
        self.db = self.client[self.database]
        self.connect_result = False
        if self.username and self.password:
            self.connect_result = self.db.authenticate(self.username,self.password)


    def aggregate_two_collection(self):
        collection_one = "test2"
        collection_two = "test1"
        lookup_dict = {"$lookup":{"from":collection_two,"localField":"_id","foreignField":"brand_id","as":"brand_product"}}
        result = self.db[collection_one].aggregate([lookup_dict])
        for r in result:
            print(r)

p = PyMongoTest()
p.aggregate_two_collection()

# 結果
{'_id': ObjectId('5e7c756b2a89d7c2fc178f57'), 'brand': '惠普公司', 'address': '美國', 'brand_product': []}

 

將test2改為

{
    "_id" : ObjectId("5e7c756b2a89d7c2fc178f57"),
    "brand" : "惠普公司",
    "address" : "美國",
    "oid" : "5e7c756b2a89d7c2fc178f57"
}
    def aggregate_two_collection(self):
        collection_one = "test2"
        collection_two = "test1"
        lookup_dict = {"$lookup":{"from":collection_two,"localField":"oid","foreignField":"brand_id","as":"brand_product"}}
        result = self.db[collection_one].aggregate([lookup_dict])
        for r in result:
            print(r)

# 結果
{'_id': ObjectId('5e7c756b2a89d7c2fc178f57'), 'brand': '惠普公司', 'address': '美國', 'oid': '5e7c756b2a89d7c2fc178f57', 'brand_product': [{'_id': ObjectId('5e7c753b2a89d7c2fc178f38'), 'name': '暗夜精靈筆記本電腦', 'brand_id': '5e7c756b2a89d7c2fc178f57'}, {'_id': ObjectId('5e7c75d02a89d7c2fc178fb0'), 'name': '暗夜精靈2', 'brand_id': '5e7c756b2a89d7c2fc178f57', 'price': 5600}]}

 

可以看出:from是要關聯的集合名,localField是關聯的字段,foreignField也是關聯的字段,但是必須注意,這兩個字段的類型必須相同,要不就拿不出數據,as就是關聯后,列表的名稱

修改test1

/* 1 */
{
    "_id" : ObjectId("5e7c753b2a89d7c2fc178f38"),
    "name" : "暗夜精靈筆記本電腦",
    "brand_id" : "5e7c756b2a89d7c2fc178f57F",
  
} /* 2 */ { "_id" : ObjectId("5e7c75d02a89d7c2fc178fb0"), "name" : "暗夜精靈2", "brand_id" : "5e7c756b2a89d7c2fc178f57D", "price" : 5600 }
{'_id': ObjectId('5e7c756b2a89d7c2fc178f57'), 'brand': '惠普公司', 'address': '美國', 'oid': '5e7c756b2a89d7c2fc178f57', 'brand_product': []}

 

說明 localField是關聯的字段,foreignField也是關聯的字段,值也必須相同。

將test1兩個數據的brand_id修改成和test1的oid值一樣,做下面測試

關聯后,只想輸出部分字段,怎么辦?

    def aggregate_two_collection(self):
        collection_one = "test2"
        collection_two = "test1"
        lookup_dict = {"$lookup":{"from":collection_two,"localField":"oid","foreignField":"brand_id","as":"brand_product"}}
        project_dict = {"$project":{"_id":0,"oid":0}}
        result = self.db[collection_one].aggregate([lookup_dict,project_dict])
        for r in result:
            print(r)

# 結果
{'brand': '惠普公司', 'address': '美國', 'brand_product': [{'_id': ObjectId('5e7c753b2a89d7c2fc178f38'), 'name': '暗夜精靈筆記本電腦', 'brand_id': '5e7c756b2a89d7c2fc178f57'}, {'_id': ObjectId('5e7c75d02a89d7c2fc178fb0'), 'name': '暗夜精靈2', 'brand_id': '5e7c756b2a89d7c2fc178f57', 'price': 5600}]}

 

project只影響原表的字段輸出,不影響要關聯表的字段,如果需要影響要關聯表的字段輸出呢?

更改test1數據為

/* 1 */
{
    "_id" : ObjectId("5e7c753b2a89d7c2fc178f38"),
    "name" : "暗夜精靈筆記本電腦",
    "brand_id" : "5e7c756b2a89d7c2fc178f57",
    "price" : 5000
}

/* 2 */
{
    "_id" : ObjectId("5e7c75d02a89d7c2fc178fb0"),
    "name" : "暗夜精靈2",
    "brand_id" : "5e7c756b2a89d7c2fc178f57",
    "price" : 5600
}
    def aggregate_two_collection(self):
        collection_one = "test2"
        collection_two = "test1"
        lookup_dict = {"$lookup":{"from":collection_two,"localField":"oid","foreignField":"brand_id","as":"brand_product"}}
        project_dict = {"$project":{"_id":0,"brand_product._id":0}}
        result = self.db[collection_one].aggregate([lookup_dict,project_dict])
        for r in result:
            print(r)


#結果
{'brand': '惠普公司', 'address': '美國', 'oid': '5e7c756b2a89d7c2fc178f57', 'brand_product': [{'name': '暗夜精靈筆記本電腦', 'brand_id': '5e7c756b2a89d7c2fc178f57', 'price': 5000}, {'name': '暗夜精靈2', 'brand_id': '5e7c756b2a89d7c2fc178f57', 'price': 5600}]}

 

計算兩款電腦的平均值?

 def aggregate_two_collection(self):
        collection_one = "test2"
        collection_two = "test1"
        lookup_dict = {"$lookup":{"from":collection_two,"localField":"oid","foreignField":"brand_id","as":"brand_product"}}
        project_dict = {"$project":{"_id":0,"brand_product._id":0}}
        unwind_dict = {"$unwind":"$brand_product"}
        group_dict = {"$group":{"_id":{"oid":"$oid"},"avg_price":{"$avg":"$brand_product.price"}}}
        result = self.db[collection_one].aggregate([lookup_dict,project_dict,unwind_dict,group_dict])
        for r in result:
            print(r)


# 結果
{'_id': {'oid': '5e7c756b2a89d7c2fc178f57'}, 'avg_price': 5300.0}

 

$substr 切割字符串操作

/* 1 */
{
    "_id" : ObjectId("5e7dc3322a89d7c2fc18605d"),
    "animal_number" : "1001",
    "status" : "0",
    "time" : ISODate("2020-03-01T23:00:00.000Z")
}

/* 2 */
{
    "_id" : ObjectId("5e7dc3462a89d7c2fc18606e"),
    "animal_number" : "1001",
    "status" : "1",
    "time" : ISODate("2020-03-01T12:00:00.000Z")
}

/* 3 */
{
    "_id" : ObjectId("5e7dc35d2a89d7c2fc186093"),
    "animal_number" : "1001",
    "status" : "0",
    "time" : ISODate("2020-03-02T15:00:00.000Z")
}

/* 4 */
{
    "_id" : ObjectId("5e7dc3702a89d7c2fc1860a4"),
    "animal_number" : "1001",
    "status" : "1",
    "time" : ISODate("2020-03-02T22:33:00.000Z")
}

/* 5 */
{
    "_id" : ObjectId("5e7dc3912a89d7c2fc1860c3"),
    "animal_number" : "1001",
    "status" : "0",
    "time" : ISODate("2020-03-03T21:39:00.000Z")
}

/* 6 */
{
    "_id" : ObjectId("5e7dc39e2a89d7c2fc1860ce"),
    "animal_number" : "1001",
    "status" : "1",
    "time" : ISODate("2020-03-04T23:00:00.000Z")
}

 

獲取每天status為0的次數,和status為1的次數

    def aggregate(self):
        match_dict = {"$match":{"animal_number":"1001"}}
        project = {"$project":{"_id":0,"animal_number":"$animal_number","status":"$status","time":{"$substr":["$time",0,10]}}}
        result = self.db["test2"].aggregate([match_dict,project])
        for info in result:
            print(info)

# 結果
{'animal_number': '1001', 'status': '0', 'time': '2020-03-01'}
{'animal_number': '1001', 'status': '1', 'time': '2020-03-01'}
{'animal_number': '1001', 'status': '0', 'time': '2020-03-02'}
{'animal_number': '1001', 'status': '1', 'time': '2020-03-02'}
{'animal_number': '1001', 'status': '0', 'time': '2020-03-03'}
{'animal_number': '1001', 'status': '1', 'time': '2020-03-04'}

project里面使用 "status":1和"status":"$status"表示的含義一樣,均表示需要展示
$substr:["$需要切割字段的名字",起始位置,終止位置]
 def aggregate(self):
        match_dict = {"$match":{"animal_number":"1001"}}
        project = {"$project":{"_id":0,"animal_number":"$animal_number","status":"$status","time":{"$substr":["$time",0,10]}}}
        group_dict = {"$group":{"_id":{"time":"$time","status":"$status"},"every_status_every_day_count":{"$sum":1}}}
        result = self.db["test2"].aggregate([match_dict,project,group_dict])
        for info in result:
            print(info)

# 結果
{'_id': {'time': '2020-03-03', 'status': '0'}, 'every_status_every_day_count': 1}
{'_id': {'time': '2020-03-04', 'status': '1'}, 'every_status_every_day_count': 1}
{'_id': {'time': '2020-03-01', 'status': '1'}, 'every_status_every_day_count': 1}
{'_id': {'time': '2020-03-01', 'status': '0'}, 'every_status_every_day_count': 1}
{'_id': {'time': '2020-03-02', 'status': '0'}, 'every_status_every_day_count': 1}
{'_id': {'time': '2020-03-02', 'status': '1'}, 'every_status_every_day_count': 1}

 

# 項目中碰到的一次關聯查詢記錄,本地字段為string,被關聯的字段為ObjectId

role表

{
    "_id" : ObjectId("60c374a466548e27b554619e"),
    "name" : "admin",
    "alist" : [ 
        "60c374e166548e27b554624e", 
        "60c374ed66548e27b5546270"
    ]
}

/* 2 */
{
    "_id" : ObjectId("60c374bc66548e27b55461dd"),
    "name" : "auth",
    "alist" : [ 
        "60c374e166548e27b554624e", 
        "60c374ed66548e27b5546270"
    ]
}

 

authority表

/* 1 */
{
    "_id" : ObjectId("60c374e166548e27b554624e"),
    "name" : "book"
}

/* 2 */
{
    "_id" : ObjectId("60c374ed66548e27b5546270"),
    "name" : "log"
}

 

要求:查詢所有role的所有權限

def test():
    match = {"$match": {"_id": {"$ne": ""}}}
    project = {"$project": {"_id": 0, "name": 1, "alist": 1}}
    # 拆分列表
    uwind = {"$unwind": "$alist"}
    # 增加字段,將str轉換為ObjectId, 曲線救國
    str_objid = {"$addFields": {"oid": {"$convert": {"input": "$alist", "to": "objectId"}}}}
    # 關聯查詢:本地字段和被關聯字段的類型必須一致才可以。
    lookup = {"$lookup":
                  {"from": "authority", "localField": "oid", "foreignField": "_id", "as": "infos"}}
    result = conn["test"]["role"].aggregate([match, project, uwind, str_objid, lookup])
    for info in result:
        print(info)

    # {'name': 'admin', 'alist': '60c374e166548e27b554624e', 'oid': ObjectId('60c374e166548e27b554624e'), 'infos': [{'_id': ObjectId('60c374e166548e27b554624e'), 'name': 'book'}]}
    # {'name': 'admin', 'alist': '60c374ed66548e27b5546270', 'oid': ObjectId('60c374ed66548e27b5546270'), 'infos': [{'_id': ObjectId('60c374ed66548e27b5546270'), 'name': 'log'}]}
    # {'name': 'auth', 'alist': '60c374e166548e27b554624e', 'oid': ObjectId('60c374e166548e27b554624e'), 'infos': [{'_id': ObjectId('60c374e166548e27b554624e'), 'name': 'book'}]}
    # {'name': 'auth', 'alist': '60c374ed66548e27b5546270', 'oid': ObjectId('60c374ed66548e27b5546270'), 'infos': [{'_id': ObjectId('60c374ed66548e27b5546270'), 'name': 'log'}]}


test()

雖然查出來了,但明顯感覺到,執行效率比較低,總結出來,造成這種問題的原因是表設計的不合理。

 

要求:將數據庫存儲的時間類型轉成str類型 --- 2021-07-21

match_dict = {"$match": {"candle_begin_time": {"$gte": datetime(year=2019, month=1, day=1, hour=0, minute=0, second=0),"$lte": datetime(year=2019, month=12, day=31, hour=23, minute=59, second=59)}}}

project_dict = {"$project": {"_id": 0, "candle_begin_time":{"$dateToString":{"format":"%Y/%m/%d", "date":"$candle_begin_time"}}}}

 object轉為str關聯查詢

match_dict = {"$match":{"_id":ObjectId('610bd2c2f55ef3718d873d24')}}
str_objid = {"$addFields": {"str_id": {"$toString":"$_id"}}}
lookup_dict = {"$lookup":{"from":"risk_control_info","localField":"str_id","foreignField":"strategy_id","as":"infos"}}
ret_ = mongo_wrapper_sys.aggregate_common(collection="strategy_info",pipeline=[match_dict,str_objid,lookup_dict])

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM