elasticsearch6.7 05. Document APIs(10)Reindex API

来源:https://www.cnblogs.com/wtc1994/archive/2019/04/15/10708497.html
-Advertisement-
Play Games

9、REINDEX API Reindex要求為源索引中的所有文檔啟用_source。 不會配置目標索引,不會複製源索引的設置。你需要在reindex之前先指定 ,分片數量,副本數量等選項。 最常用的一種方式是複製一個索引。下例會將twitter索引中的文檔複製到new_twitter索引中: 返回 ...


9、REINDEX API

Reindex要求為源索引中的所有文檔啟用_source。

reindex 不會配置目標索引,不會複製源索引的設置。你需要在reindex之前先指定mapping,分片數量,副本數量等選項。

_reindex最常用的一種方式是複製一個索引。下例會將twitter索引中的文檔複製到new_twitter索引中:

POST _reindex
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  }
}

返回結果:

{
  "took" : 147,
  "timed_out": false,
  "created": 120,
  "updated": 0,
  "deleted": 0,
  "batches": 1,
  "version_conflicts": 0,
  "noops": 0,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": -1.0,
  "throttled_until_millis": 0,
  "total": 120,
  "failures" : [ ]
}

_update_by_query API 一樣,_reindex從原索引獲取快照,但它的目標索引必須是不同的索引,所以不太可能發生版本衝突。dest元素可以向 index API 一樣配置,控制樂觀鎖。例如,省略version_type(和上述一樣)或者將其設置為internal,會導致Elasticsearch草率地將文檔轉儲到目標索引,從而恰巧覆蓋具有相同type和id的文檔:

POST _reindex
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "version_type": "internal"
  }
}

設置version_typeexternal會使Elasticsearch保存源文檔的version,創建任何不存在目標索引的文檔,並更新任何源文檔version比目標文檔version要大的文檔:

POST _reindex
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "version_type": "external"
  }
}

設置op_typecreate 會導致 _reindex僅在目標索引中創建缺少的文檔。索引已存在的文檔都會導致版本衝突:

POST _reindex
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "op_type": "create"
  }
}

預設的版本衝突會導致_reindex 進程終止,你可以在請求體中設置"conflicts": "proceed"來指示_reindex繼續處理版本衝突之後的文檔。請務必註意,其他錯誤類型的處理不受“conflict”參數的影響。當請求體中設置"conflicts": "proceed"時,_reindex進程將繼續發生版本衝突並返回遇到的版本衝突數:

POST _reindex
{
  "conflicts": "proceed",
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "op_type": "create"
  }
}

你可以通過在source欄位內添加type欄位或query欄位來限制文檔。如下例僅會將索引twitter中的kimchy複製到索引new_twitter中:

POST _reindex
{
  "source": {
    "index": "twitter",
    "type": "_doc",
    "query": {
      "term": {
        "user": "kimchy"
      }
    }
  },
  "dest": {
    "index": "new_twitter"
  }
}

可以在source欄位中同時列出typeindex,允許在一個請求中複製大量數據。下例會複製來自twitter索引和blog索引的_doc 類型和post類型的文檔:

POST _reindex
{
  "source": {
    "index": ["twitter", "blog"],
    "type": ["_doc", "post"]
  },
  "dest": {
    "index": "all_together",
    "type": "_doc"
  }
}

Reindex API 不會處理ID衝突,以最後寫入的文檔為準,但reindex的順序通常是不可預測,因此依賴此行為並不是一個好主意。應該使用腳本確保ID是唯一的。

也可以限制複製文檔的數量。下例僅僅從twitter索引複製一個文檔到new_twitter索引:

POST _reindex
{
  "size": 1,
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  }
}

你可以指定設置sort參數指定排序規則。sort會降低scroll的效率,但是有時候必須使用。如果可以的話,最好限制size的大小。下例會從twitter索引中複製10000個文檔到new_twitter索引:

POST _reindex
{
  "size": 10000,
  "source": {
    "index": "twitter",
    "sort": { "date": "desc" }
  },
  "dest": {
    "index": "new_twitter"
  }
}

可以使用_source參數過濾欄位,例如,可以使用sourcetwitter索引中過濾一部分欄位,如下所示:

POST _reindex
{
  "source": {
    "index": "twitter",
    "_source": ["user", "_doc"]
  },
  "dest": {
    "index": "new_twitter"
  }
}

_redix_update_by_query一樣也支持腳本,它可以修改一個文檔,但和_update_by_query有區別,這個script僅允許修改文檔的metadata

POST _reindex
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter",
    "version_type": "external"
  },
  "script": {
    "source": "if (ctx._source.foo == 'bar') {ctx._version++; ctx._source.remove('foo')}",
    "lang": "painless"
  }
}

_update_by_query一樣,你可以設置ctx.op改變在目標索引執行的操作:

  • noop
    • 設置 ctx.op = "noop",如果你的script確定文檔不需要索引到目標索引。這個空操作將會反映到響應體的noop計數器。
  • delete
    • 設置ctx.op = "delete",如果你的script確定必須要從目標索引中刪除文檔。刪除操作會反映到響應體的deleted計數器。

設置ctx.op為其他值會導致錯誤。

你甚至可以改變如下的元數據,但一定要小心地操作:

  • _id
  • _type
  • _index
  • _version
  • _routing
  • _parent

設置_version =null或者從ctx中清空它,等價於沒有在index 請求中發送version參數。不管目標索引文檔的版本或者你在_reindex請求中指定的版本類型是什麼,它都會導致目標索引的文檔被覆蓋。

預設情況下,如果_reindex查詢到一個指定了routing參數的文檔,在新文檔中也會保留該參數,除非你在script中改變它。你可以在dest欄位設置routing從而改變這個設置:

  • keep
    • 文檔的路由值在新索引中保持不變。這是預設值。
  • discard
    • 原索引中文檔的routing值在新索引中變為null
  • =<some text>
    • 文檔的路由值在新索引中變為指定值。

例如,你可以使用以下請求從源索引中複製所有公司名是cat的文檔到目標索引,並且指定它們的routing值都是cat:

POST _reindex
{
  "source": {
    "index": "source",
    "query": {
      "match": {
        "company": "cat"
      }
    }
  },
  "dest": {
    "index": "dest",
    "routing": "=cat"
  }
}

預設,_reindex每次scroll查詢的文檔數是1000。你可以在source元素中使用size參數改變這個大小:

POST _reindex
{
  "source": {
    "index": "source",
    "size": 100
  },
  "dest": {
    "index": "dest",
    "routing": "=cat"
  }
}

你也可以指定pipeline參數使用Ingest Node節點特性:

POST _reindex
{
  "source": {
    "index": "source"
  },
  "dest": {
    "index": "dest",
    "pipeline": "some_ingest_pipeline"
  }
}

9.1 從遠程重建索引(Reindex from Remote)

reindex支持從遠程的集群中獲取源索引數據:

POST _reindex
{
  "source": {
    "remote": {
      "host": "http://otherhost:9200",
      "username": "user",
      "password": "pass"
    },
    "index": "source",
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "dest"
  }
}

host參數必須包含協議,主機和埠(例如:https://otherhost:9200)和可選路徑(例如https://otherhost:9200/proxy)。usernamepassword是可選的,當Elasticsearch節點需要basic auth時會使用它們。使用基本身份驗證時務必使用https,否則密碼將以純文本格式發送。有一系列設置可用於配置https連接的行為。

遠程主機必須要在elasticsearch.yaml使用reindex.remote.whitelist屬性顯式指定允許連接的白名單。它可以是一個逗號分隔的列表((e.g. otherhost:9200, another:9200, 127.0.10.*:9200, localhost:*)。白名單忽略協議,僅僅使用埠和主機。例如:

reindex.remote.whitelist: "otherhost:9200, another:9200, 127.0.10.*:9200, localhost:*"

必須將白名單配置在所有進行reindex的節點上。

這個特性可以和任何版本的遠程集群交互。允許你從任何版本的Elasticsearch升級到當前版本。

要將查詢發送到舊版的Elasticsearch,請將查詢參數直接發送到遠程主機。

從遠程群集執行reindex 不支持手動或自動切片。

遠程伺服器使用一個最大值是100mb的緩衝區。如果遠程索引包含非常大的文檔,你需要使用一個更小的批量大小(每一批的數量不要超過緩衝區大小),下麵的示例將批量大小設置為10:

POST _reindex
{
  "source": {
    "remote": {
      "host": "http://otherhost:9200"
    },
    "index": "source",
    "size": 10,
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "dest"
  }
}

你也可以使用socket_timeout欄位指定請求的套接字進行讀取操作的超時時間,connect_timeout欄位指定連接超時時間。預設都是30s。下例將套接字讀取超時設置為一分鐘,將連接超時設置為10秒:

POST _reindex
{
  "source": {
    "remote": {
      "host": "http://otherhost:9200",
      "socket_timeout": "1m",
      "connect_timeout": "10s"
    },
    "index": "source",
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "dest"
  }
}

9.2 url參數(URL Parameters)

參考上一節

9.3 配置SSL參數(Configuring SSL parameters)

9.4 響應體(Response body)

json響應如下:

{
  "took": 639,
  "timed_out": false,
  "total": 5,
  "updated": 0,
  "created": 5,
  "deleted": 0,
  "batches": 1,
  "noops": 0,
  "version_conflicts": 2,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": 1,
  "throttled_until_millis": 0,
  "failures": [ ]
}
  • took
    • 整個操作耗費的毫秒數
  • timed_out
    • 如果在執行 reindex 操作時出現超時,那麼這個標識將會返回 true
  • total
    • 成功執行操作的文檔的數量
  • updated
    • 成功的更新了多少個文檔
  • ceated
    • 成功的創建了多少個文檔
  • deleted
    • 成功的刪除了多少個文檔
  • batches
    • 回滾數
  • verison_conflicts
    • 操作過程中出現版本衝突的數量
  • noops
    • 由於 ctx.op=noop 設置造成的忽略的文檔數
  • retries
    • 重覆嘗試的次數,bulk 是批量更新操作重覆嘗試的次數,search 是查詢的重覆嘗試次數
  • throthled_millis
    • requests_per_second 參數引起的請求等待時間
  • requests_per_second
    • 在操作過程中,每秒執行的請求數
  • throttled_until_millis
    • 執行reindex時這個值始終0,只在在調用Task API時該值才有意義,它表示下一次(自紀元以來)為了符合requests_per_second將再次執行請求的毫秒數。
  • failures
    • 執行失敗的數組,包含在執行過程中任何不可恢復的錯誤。如果這個數組不是空的,那麼請求會因為這些失敗而中止。reindex 是使用批處理實現的,任何失敗都會導致整個執行被中止。可以使用conflicts參數來防止reindex在版本衝突時造成操作中止。

9.5 結合 taskAPi 使用(Works with the Task API)

您可以使用 Task API 獲取任何正在進行 update_by_query 請求的狀態:

GET _tasks?detailed=true&actions=*reindex 

返回值:

{
  "nodes" : {
    "r1A2WoRbTwKZ516z6NEs5A" : {
      "name" : "r1A2WoR",
      "transport_address" : "127.0.0.1:9300",
      "host" : "127.0.0.1",
      "ip" : "127.0.0.1:9300",
      "attributes" : {
        "testattr" : "test",
        "portsfile" : "true"
      },
      "tasks" : {
        "r1A2WoRbTwKZ516z6NEs5A:36619" : {
          "node" : "r1A2WoRbTwKZ516z6NEs5A",
          "id" : 36619,
          "type" : "transport",
          "action" : "indices:data/write/reindex",
          "status" : {    
            "total" : 6154,
            "updated" : 3500,
            "created" : 0,
            "deleted" : 0,
            "batches" : 4,
            "version_conflicts" : 0,
            "noops" : 0,
            "retries": {
              "bulk": 0,
              "search": 0
            },
            "throttled_millis": 0,
            "requests_per_second": -1,
            "throttled_until_millis": 0
          },
          "description" : "",
          "start_time_in_millis": 1535149899665,
          "running_time_in_nanos": 5926916792,
          "cancellable": true,
          "headers": {}
        }
      }
    }
  }
}

status:這個對象包含了當前任務的實際狀態。total 欄位是本次操作需要重新索引的文檔數。你可以通過 updated, created, and deleted 欄位估計處理進度。當以上幾個欄位的和等於 total 欄位時,請求就執行完畢了。

你可以使用 task id 查看某個任務。下例查看task id為 r1A2WoRbTwKZ516z6NEs5A:36619的任務信息:

GET /_tasks/r1A2WoRbTwKZ516z6NEs5A:36619

該 API 可以與wait_for_comletion=false集成使用,可以清晰的查看已完成任務的狀態。如果任務已經完成,並且在其上設置了wait_for_completion=false,那麼請求將會返回結果或是錯誤欄位。此功能的代價是當wait_for_completion=false時會在.tasks/task/${taskId}目錄下會創建文檔。您可以根據需要刪除該文檔。

9.6 取消任務(Works with the Cancel Task API)

任何_update_by_query操作都可以通過task cancel API來取消,如:

POST _tasks/r1A2WoRbTwKZ516z6NEs5A:36619/_cancel

取消應該執行很快,但可能需要幾秒鐘。在此期間上面的 task status API將繼續列出該任務,直到它完全被取消了。

9.7 閾值(Rethrottling)

在正在執行的請求中,requests_per_second的值可以在運行時通過_rethrotted API進行修改:

POST _update_by_query/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1

可以使用tasks API找到任務ID。

和 requests_per_seconds 參數設置一樣,rethrottling 參數可以是 - 1 (禁用限制)或是其他十進位數(如 1.7 或 12 )。rethrottling 參數能提高查詢速度且會立即生效,但是降低速度必須等到當前操作執行完後才起作用。這可以防止滾動超時

9.7.1 重建索引以更改欄位的名稱

_reindex可用於構建具有重命名欄位的索引副本。假設您創建一個包含如下所示文檔的索引:

POST test/_doc/1?refresh
{
  "text": "words words",
  "flag": "foo"
}

但你不喜歡flag ,並希望用tag替換它。可以如下創建另一個索引:

POST _reindex
{
  "source": {
    "index": "test"
  },
  "dest": {
    "index": "test2"
  },
  "script": {
    "source": "ctx._source.tag = ctx._source.remove(\"flag\")"
  }
}

查詢新的文檔:

GET test2/_doc/1

響應結果:

{
  "found": true,
  "_id": "1",
  "_index": "test2",
  "_type": "_doc",
  "_version": 1,
  "_seq_no": 44,
  "_primary_term": 1,
  "_source": {
    "text": "words words",
    "tag": "foo"
  }
}

9.8 切片 (slicing)

Reindex 支持 sliced scroll 來使 reindex 操作並行進行。這能提高效率並且提供了一種將請求分解為較小的部分的便捷方式。

9.8.1 手動切片 (Manually slicing)

通過為每個請求提供切片 ID 和切片總數,手動將 _reindex 操作進行分解:

POST _reindex
{
  "source": {
    "index": "twitter",
    "slice": {
      "id": 0,
      "max": 2
    }
  },
  "dest": {
    "index": "new_twitter"
  }
}
POST _reindex
{
  "source": {
    "index": "twitter",
    "slice": {
      "id": 1,
      "max": 2
    }
  },
  "dest": {
    "index": "new_twitter"
  }
}

你可以這樣驗證上述 api 的結果:

GET _refresh
POST new_twitter/_search?size=0&filter_path=hits.total

返回如下的的結果:

{
  "hits": {
    "total": 120
  }
}

9.8.2 自動切片 (Automatic slicing)

也可以讓 _reindex 自動並行地滾動切片。使用 slices 指定要使用的切片數:

POST _reindex?slices=5&refresh
{
  "source": {
    "index": "twitter"
  },
  "dest": {
    "index": "new_twitter"
  }
}

您可以通過下列語句驗證運行結果:

POST new_twitter/_search?size=0&filter_path=hits.total

返回如下的的結果:

{
  "hits": {
    "total": 120
  }
}

slices 設置為 auto 將允許 ElasticSearch 選擇要使用的切片數。此設置將使用一個分片一個切片,直至達到某個限制。如果存在多個源索引,它將根據具有最少分片的那個索引所擁有的分片數來作為切片數。

_reindex 添加 slices 只會自動執行上一節中使用的手動過程,這意味著它有一些怪癖:

  • 您可以在 Tasks API 中查看這些請求。這些子請求是具有 slices 請求的任務的 “子 " 任務。
  • 僅使用 slices 獲取請求的任務狀態 (包含已完成切片的狀態)。
  • 這些子請求可單獨定址,例如取消和重新限制。
  • 使用 slices 重新處理請求將按比例重新調整未完成的子請求。
  • 使用 slices 取消請求將取消每個子請求。
  • 由於 slices 的性質,每個子請求都不會獲得完全均勻的文檔部分。這些切片文檔都會被處理,但某些切片可能比其他切片分到更大的文檔。
  • requests_per_second 這樣的參數和帶有 sizeslices 請求 (按指定比例分配給每個子請求)。將其與上述關於分佈不均勻的點相結合,您應該得出結論,使用 slicessize 可能不會刪除指定大小的文檔。
  • 每個子請求都會獲得和源索引略有不同的快照,儘管這些快照幾乎同時進行。

9.8.3 選擇 slices 的數量(Picking the number of slices)

如果 slices 設置為 auto,elasticsearch 將會自動為大多數索引選擇一個合理的數量。如果您設置手動切片或以其他方式來調整自動切片,請遵循以下準則:

當切片的數量等於索引的分片數時,查詢性能最好。如果這個數量太大(如 500), 請選擇一個較小的數字,因為太多的切片會影響性能。設置高於分片數的切片通常不會提高效率反而會增加開銷。

indexing 的性能與可用的切片數量呈正相關。

查詢或索引是否是影響此時運行時性能的主要原因,這取決於reindexed時的文檔和集群的資源。

9.9 重建更多的索引( Reindexing many indices)

如果你有很多索引要重新索引,通常最好一次重新索引它們,而不是使用全局模式來獲取許多索引。這樣的話如果reindex時有任何錯誤,您可以通過刪除部分已完成的索引,然後讓該索引重新執行一次reindex,從而恢復之前的流程。它還使得流程的並行化非常簡單:將索引列表拆分為reindex並並行運行每個列表。

One-off bash腳本似乎很適合這種操作:

for index in i1 i2 i3 i4 i5; do
  curl -HContent-Type:application/json -XPOST localhost:9200/_reindex?pretty -d'{
    "source": {
      "index": "'$index'"
    },
    "dest": {
      "index": "'$index'-reindexed"
    }
  }'
done

9.10 每日重覆指數( Reindex daily indices)

儘管有上述建議,您可以將_reindex與Painless結合使用新模板應用於現有文檔以實現每日重建索引。

假設您的索引由以下文檔組成:

PUT metricbeat-2016.05.30/_doc/1?refresh
{"system.cpu.idle.pct": 0.908}
PUT metricbeat-2016.05.31/_doc/1?refresh
{"system.cpu.idle.pct": 0.105}

metricbement- *索引的新模板已載入到Elasticsearch中,但它僅適用於新創建的索引。Painless 可用於reindex 已經存在的文檔並應用於新模板。

下麵的腳本從索引名稱中提取日期,並創建一個在原索引上附加了-1的新的索引。下例將metricbeat-2016.05.31索引中的所有數據都重新編入metricbeat-2016.05.31-1索引中。

POST _reindex
{
  "source": {
    "index": "metricbeat-*"
  },
  "dest": {
    "index": "metricbeat"
  },
  "script": {
    "lang": "painless",
    "source": "ctx._index = 'metricbeat-' + (ctx._index.substring('metricbeat-'.length(), ctx._index.length())) + '-1'"
  }
}

現在可以在* -1索引中找到先前metricbeat索引中的所有文檔:

GET metricbeat-2016.05.30-1/_doc/1
GET metricbeat-2016.05.31-1/_doc/1

以前的方法還可以與更改欄位名稱結合使用,以僅將現有數據載入到新索引中,並根據需要重命名任何欄位。

9.11 提取索引的隨機子集(Extracting a random subset of an index)

_reindex可用於提取索引的隨機子集以進行測試:

POST _reindex
{
  "size": 10,
  "source": {
    "index": "twitter",
    "query": {
      "function_score" : {
        "query" : { "match_all": {} },
        "random_score" : {}
      }
    },
    "sort": "_score"    【1】
  },
  "dest": {
    "index": "random_twitter"
  }
}

【1】:_reindex預設按_doc排序,除非您將排序覆蓋為_score,否則random_score將不起作用。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 抽象工廠模式概述 定義:提供一個創建一系列相關或相互依賴對象的介面,而無需指定他們具體的類 抽象工廠抽象工廠,顧名思義,就是比工廠模式更抽象的工廠模式。在工廠模式中,一個具體工廠只負責生產一個具體產品。而在抽象工廠模式中,一個具體工廠可以生產一組相關的產品,這些產品稱為產品族,產品族中的每一個產品部 ...
  • 前言: 現在我們生活中已經離不開微信,QQ等交流軟體,這對於我們來說不僅是交流,更有在朋友圈中或空間中進行分享自己的生活,同時也可以通過這個渠道知道別人的生活。我們在看朋友圈的時候其實我們扮演的就是一個觀察者,朋友圈或空間里的動態可以看作是主體對象。接下來我們就介紹一下觀察者模式 一、定義 定義了對 ...
  • 前段時間看到一份代碼,小規模、低難度的一個應用,MVC用到極致,業務邏輯卻混成一團麻,應該是中了培訓班的毒。現在的程式員,大多是沒仔細讀過《現代操作系統》,沒看過編譯原理,不知道堆與棧,沒怎麼用過C、C++,上手就Java、C#,程式一開就記憶體狂飆,資料庫連接隨手就建,但這種人算是相當多了,見多了也 ...
  • [TOC] 一、Redis Cluster簡單介紹 搭建的方式有多種,例如使用Redis主從複製+Sentinel高可用集群、zookeeper等,但從 之後版本支持Redis cluster集群, "Redis Cluster" 採用無中心結構,每個節點保存數據和整個集群狀態,每個節點都和其他所有 ...
  • 前言 不管在我們的工作還是生活中,總會出現各種“錯誤”,各種突發的“異常”。無論我們做了多少準備,多少測試,這些異常總會在某個時間點出現,如果處理不當或是不及時,往往還會導致其他新的問題出現。所以我們要時刻註意這些陷阱以及需要一套“最佳實踐”來建立起一個完善的異常處理機制。 正文 異常分類 首先,這 ...
  • 這些都是之前在CSDN寫的,那裡廣告太多,現在打算搬家了!直接弄幾個超鏈接吧 Lambda表達式 方法引用 構造器引用 數組引用 Stream API ...
  • 1 . 偏函數 (partial) 最終得到的結果為: ( (1, 2, 3, 4) , {'a': 3, 'b': 5} ) 我理解的意思為: 將1,2,3,4,a=3,b=5傳入func中去執行函數. 其實就是 :往函數里傳一個值不執行,返回一個新函數 2.ThreadingLocal線程安全 ...
  • [TOC] 介紹 通過本項目能夠更直觀地理解應用層和運輸層網路協議, 以及繼承封裝多態的運用. 網路部分是本文敘述的重點, 你將看到如何使用Java建立TCP和UDP連接並交換報文, 你還將看到如何自己定義一個簡單的應用層協議來讓自己應用進行網路通信. "獲取源碼" 基礎版本 游戲的原理, 圖形界面 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...