2024-08-24

本文面向在使用 Vue(含 Vue CLI / webpack / Vite) 开发时遇到 “BREAKING CHANGE: webpack < 5 used to include polyfills…” 或 “Buffer is not defined / process is not defined / 不能解析 Node core modules” 等错误的工程师。文章包含原理解释、常见场景、逐步修复方案(可复制的代码片段)、以及针对 Vue CLI、纯 webpack、和 Vite 的具体配置示例、调试要点与替代方案,方便你快速上手并彻底解决问题。关键结论与改法在正文中并带来源引用,便于深入查证。(webpack)


摘要(为什么会报这个错?)

Webpack 5 取消了对 Node.js 核心模块(如 crypto, stream, path, os, buffer, process 等)的自动浏览器端 polyfill。旧版本(webpack < 5)在构建浏览器包时会自动提供这些 polyfills;升级到 webpack 5 后,若你的依赖(或其依赖)在浏览器端仍然 require('crypto') 或使用 Buffer / process,构建就会报错并提示需要手动配置 polyfill 或显式禁用(false)。这就是报错的根源:缺少 polyfill。(GitHub)


目录

  1. 发生场景与典型错误提示
  2. 可选策略总览(短)
  3. 方案 A:使用 node-polyfill-webpack-plugin(最简单)
  4. 方案 B:手动配置 resolve.fallback + ProvidePlugin(更可控)
  5. Vue CLI 项目:在 vue.config.js 中做改动(示例)
  6. Vite(Vue 3 + create-vue):如何处理(替代方式)
  7. 常见模块的替代包与安装命令(一键清单)
  8. 调试与验证(如何确认已生效)
  9. 性能与包体积注意事项
  10. 真实案例与常见陷阱(FAQ)
  11. 总结与推荐

1. 发生场景与典型错误提示

你可能在以下情形遇到问题:

  • 在 Vue 项目中 npm run serve / npm run build 报错:
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it.
  • 浏览器运行时报 ReferenceError: Buffer is not definedprocess is not defined、或模块无法解析 cryptostream 等。
  • 升级 Vue CLI(或依赖)并迁移到 webpack 5 后出现。(GitHub)

这类错误说明:某处代码(你直接写的或第三方库)使用了 Node.js 的核心 API,而 webpack 5 默认不再自动提供这些在浏览器环境下的实现。


2. 可选策略总览(短)

面对这问题,你有几条可选策略(从简单到复杂):

  1. 为 webpack 添加一键 polyfill 插件node-polyfill-webpack-plugin(最省心)。(NPM)
  2. 手动配置 resolve.fallback + ProvidePlugin:显式控制需要哪些模块与别名(更精细)。(Stack Overflow)
  3. 如果不需要这些模块:在 resolve.fallback 中将其设为 false,以减小包体积(告诉 webpack 此模块在浏览器不需要)。(Reddit)
  4. 对于 Vite / Rollup:使用对应的 polyfill 插件或在入口处手动 shim(例如 import { Buffer } from 'buffer'; window.Buffer = Buffer)。(GitHub)

下面逐一给出具体做法与可复制配置。


3. 方案 A:使用 node-polyfill-webpack-plugin(最简单)

适用场景:只想快速修好构建、项目使用 webpack 5(包括 Vue CLI 5 使用的 webpack 5),不想逐个列出 fallback。

步骤

  1. 安装插件与常见 polyfill 包(插件会帮你引入需要的 polyfills):
npm install --save-dev node-polyfill-webpack-plugin
# 或者 yarn add -D node-polyfill-webpack-plugin
  1. 在你的 webpack.config.js 中引入并启用:
// webpack.config.js
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

module.exports = {
  // ... 你的其它 webpack 配置 ...
  plugins: [
    new NodePolyfillPlugin()
  ]
};

说明:该插件会自动添加常用 Node 核心模块的 polyfills,快速解决大多数因缺少 polyfill 导致的构建报错。适合快速修复或调试。(NPM)


4. 方案 B:手动配置 resolve.fallback + ProvidePlugin(更可控,推荐生产环境)

适用场景:你希望精确地控制哪些模块被 polyfill、哪些不被 polyfill,以减小体积或避免引入不必要的代码时使用。

4.1 安装常用 polyfill 包

常见替代实现(npm 包名):

  • buffer(Buffer)
  • stream-browserify(stream)
  • crypto-browserify(crypto)
  • path-browserify(path)
  • os-browserify(os)
  • assert(assert)
  • util(util)
  • process(process/browser)

安装示例(可一次性安装常见项):

npm install --save buffer stream-browserify crypto-browserify path-browserify os-browserify assert util process
注:有些包名后面需要加 /browser 版本(例如 buffer/),下文配置会示例。

4.2 webpack 配置(示例)

把下面的片段合并到你的 webpack.config.js(或 vue.config.jsconfigureWebpack)中:

const webpack = require('webpack');

module.exports = {
  // ... 其他配置 ...
  resolve: {
    fallback: {
      "buffer": require.resolve("buffer/"),
      "stream": require.resolve("stream-browserify"),
      "crypto": require.resolve("crypto-browserify"),
      "path": require.resolve("path-browserify"),
      "os": require.resolve("os-browserify/browser"),
      "assert": require.resolve("assert/"),
      "util": require.resolve("util/"),
      // 如果不想 polyfill 某个模块,可以写 false
      // "fs": false,
    }
  },
  plugins: [
    // ProvidePlugin 会在模块中自动注入变量,例如 Buffer, process
    new webpack.ProvidePlugin({
      Buffer: ['buffer', 'Buffer'],
      process: 'process/browser',
    }),
  ]
};

要点解释

  • resolve.fallback 会告诉 webpack 如果某个模块在浏览器环境中被 require('crypto'),就去使用 crypto-browserify 这个包来替代。若设置为 false 则表示不提供 polyfill(直接报错或跳过,取决于代码)。(Stack Overflow)
  • ProvidePlugin 自动在模块中注入 Bufferprocess,避免 ReferenceErrorBuffer 常通过 buffer 包提供。(Viglucci)

5. Vue CLI 项目:在 vue.config.js 中做改动(实战示例)

若你用的是 Vue CLI(vue-cli-service),可在项目根目录添加 vue.config.js 并通过 configureWebpack 修改 webpack 配置。示例如下:

// vue.config.js
const webpack = require('webpack');

module.exports = {
  configureWebpack: {
    resolve: {
      fallback: {
        "buffer": require.resolve("buffer/"),
        "stream": require.resolve("stream-browserify"),
        "crypto": require.resolve("crypto-browserify"),
        "path": require.resolve("path-browserify"),
        "os": require.resolve("os-browserify/browser"),
        "assert": require.resolve("assert/"),
        "util": require.resolve("util/"),
      }
    },
    plugins: [
      new webpack.ProvidePlugin({
        Buffer: ['buffer', 'Buffer'],
        process: 'process/browser',
      }),
    ]
  }
};

然后安装依赖:

npm install --save buffer stream-browserify crypto-browserify path-browserify os-browserify assert util process

重启 npm run servenpm run build。若配置正确,构建阶段的 “BREAKING CHANGE” 报错应该消失。若你希望更快速并且不想一个个手动写 fallback,可以用方案 A 的 node-polyfill-webpack-plugin。(NPM)


6. Vite(Vue 3 + create-vue):如何处理

Vite 使用的是 Rollup/esbuild,不是 webpack;因此上面 webpack 的 resolve.fallback 不适用。针对 Vite,常见做法有两种:

6.1 在入口手动 shim(简单、直接)

main.jsmain.ts 顶部加入:

// main.js
import { Buffer } from 'buffer';
window.Buffer = Buffer;

// 或者
// import process from 'process';
// window.process = process;

并安装 buffer

npm install --save buffer

这常常能解决 Buffer is not defined 或需要 process 的情况。(GitHub)

6.2 使用 Rollup 插件 / community polyfills(更完整)

  • rollup-plugin-node-polyfills:为 Rollup 提供 Node 核心模块 polyfills(可集成进 Vite 的 build.rollupOptions.plugins)。
  • vite-plugin-node-polyfills 或其它社区插件:直接注入 polyfills 或全局变量。

示例(概念):

// vite.config.js
import { defineConfig } from 'vite';
import rollupNodePolyFill from 'rollup-plugin-node-polyfills';

export default defineConfig({
  plugins: [],
  resolve: {
    alias: {
      // 某些情况下需要手动 alias
    }
  },
  build: {
    rollupOptions: {
      plugins: [
        rollupNodePolyFill()
      ]
    }
  }
});

建议:如果只需解决 Bufferprocess,入口处手动 shim 足够且包体积小;若项目依赖大量 Node API(例如 crypto、stream),考虑完整的 polyfill 插件或改用对浏览器友好的库。(GitHub)


7. 常见模块与对应浏览器替代包(一览表)

下表给出常见 Node core module 与常用 browser polyfill 包(便于 resolve.fallback 填写):

  • bufferbuffer/ (并用 ProvidePlugin 注入 Buffer). (Viglucci)
  • streamstream-browserify. (Gist)
  • cryptocrypto-browserify. (Gist)
  • pathpath-browserify. (Gist)
  • osos-browserify/browser. (Gist)
  • assertassert/. (Gist)
  • utilutil/. (Gist)
  • processprocess/browser. (Stack Overflow)

安装推荐(一次性):

npm install --save buffer stream-browserify crypto-browserify path-browserify os-browserify assert util process

8. 调试与验证(如何确认生效)

  1. 清理缓存并重建rm -rf node_modules/.cache(或直接删除 node_modulesnpm install),然后 npm run build / npm run serve
  2. 查看构建日志:若之前报错是缺少 crypto / Buffer,修好后这些错误不应再出现。
  3. 在浏览器控制台运行检查

    • 打开开发者工具控制台,输入 typeof Buffer,应返回 "function""object"(表示已注入)。
    • 输入 typeof processprocess.version(注意:在浏览器中 process.version 可能不同,但 typeof process 不应是 undefined)。
  4. Bundle 分析工具:用 webpack-bundle-analyzer 或 Vite 的 build.sourcemapvisualizer 插件查看 polyfill 是否被打包入最终产物(确认是否有意外体积飙升)。(webpack)

9. 性能与包体积注意事项

  • polyfill 会增加产物体积。尤其是 crypto-browserifystream-browserify 等会带入大量代码。生产环境建议仅 polyfill 必需的模块,避免一键把所有 Node API 都带进来。(Gist)
  • 如果某些 Node 模块实际上在浏览器端并不需要(例如 fs, child_process),应在 resolve.fallback 里写 false,并在代码或第三方库中避免使用这些模块。
  • 优先替换依赖:若第三方库只在 Node 环境使用某些功能,考虑寻找或替换为专门为浏览器实现的库(例如使用 Web Crypto API 替代某些 crypto 功能)。
  • 使用 ProvidePlugin(只为 Bufferprocess 之类的全局变量注入)比把大量 polyfill 注入模块作用域更节省,但仍需谨慎。(Viglucci)

10. 真实案例与常见陷阱(FAQ)

Q1:我在 Vue CLI 项目看到错误,但并未直接 require('crypto'),为什么?
A:通常是某个第三方库(如 web3、google-spreadsheet、ethereumjs、某些 SDK)在其内部使用了 Node API。你可以用 npm ls <pkg> 或逐步注释依赖排查,或查看构建日志中报错的模块链路找到来源。(GitHub)

Q2:我用的是 Vite,按 webpack 的方法写 resolve.fallback 没有效果。
A:Vite 使用 Rollup/esbuild,webpack 的 fallback 不适用;用入口 shim(import { Buffer } from 'buffer')或 Rollup 插件来解决。(GitHub)

Q3:为什么 Buffer 注入后仍报错?
A:可能是注入方式错了或在某些模块加载顺序上失效。使用 ProvidePlugin(webpack)或在应用入口处 window.Buffer = Buffer(Vite)通常可靠。确保 buffer 包已正确安装。(Viglucci)

Q4:我不想引入全部 polyfill,有办法只加我需要的吗?
A:可以在 resolve.fallback 中只列出确实需要的模块,并将不需要的模块设为 false。也可以逐个安装替代包并测试。(Stack Overflow)

Q5:有没有官方推荐的“一键”清单?
A:webpack 团队在官方文档 resolve 与配置项中说明如何自定义模块解析;而社区提供了 node-polyfill-webpack-plugin 可以一键注册常见 polyfills(但会带来更多代码)。两者可按需权衡。(webpack)


11. 总结与推荐(我的操作建议)

  • 若你需要 最快速 的修复(开发环境、调试或临时解决):先安装并使用 node-polyfill-webpack-plugin。(NPM)
  • 若你关注 生产体积与可控性:手动 resolve.fallback + ProvidePlugin,只 polyfill 必需模块,其他设为 false。(Stack Overflow)
  • 对于 Vite:优先在入口做 shim(window.Buffer = Bufferimport process from 'process'; window.process = process),只有在确实需要大量 Node API 时再引入 rollup 插件。(GitHub)
  • 若第三方库是罪魁祸首(例如大量 web3、google-spreadsheet 等服务端导向的库),考虑替换为浏览器友好的替代项或在构建时只打包客户端所需部分(tree-shaking / 动态 import)。(GitHub)

附录 A:快速复制的解决步骤(Vue CLI + webpack5)

  1. 安装依赖:
npm install --save buffer stream-browserify crypto-browserify path-browserify os-browserify assert util process
npm install --save-dev node-polyfill-webpack-plugin   # 可选:一键方案
  1. vue.config.js(推荐先试一键方案,如需精细控制改为下面的 manual 配置):

一键插件(最简单)

// vue.config.js
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

module.exports = {
  configureWebpack: {
    plugins: [
      new NodePolyfillPlugin()
    ]
  }
};

手动方式(更可控)

// vue.config.js
const webpack = require('webpack');

module.exports = {
  configureWebpack: {
    resolve: {
      fallback: {
        "buffer": require.resolve("buffer/"),
        "stream": require.resolve("stream-browserify"),
        "crypto": require.resolve("crypto-browserify"),
        "path": require.resolve("path-browserify"),
        "os": require.resolve("os-browserify/browser"),
        "assert": require.resolve("assert/"),
        "util": require.resolve("util/"),
      }
    },
    plugins: [
      new webpack.ProvidePlugin({
        Buffer: ['buffer', 'Buffer'],
        process: 'process/browser',
      }),
    ]
  }
};
  1. 重启服务并验证(控制台 typeof Buffer / typeof process)。

附录 B:常用参考(可点开阅读)

  • webpack resolve 配置说明(官方文档)。(webpack)
  • StackOverflow:如何在 webpack 5 中 polyfill Node core modules(详解 & 示例)。(Stack Overflow)
  • node-polyfill-webpack-plugin(npm 包说明)。(NPM)
  • Webpack 5 polyfills cheat sheet(哪些包对应哪个 core module)。(Gist)
  • 面向 create-react-app / webpack5 的实战教程(步骤详解)。(Alchemy)

报错解释:

elasticsearch.UnsupportedProductError 表明您正在使用的 Elasticsearch 客户端与运行在服务器上的 Elasticsearch 版本不兼容。这通常发生在客户端使用的API或特性与服务器端的版本不兼容时。

解决方法:

  1. 检查您的 Elasticsearch 客户端库的版本是否与您的 Elasticsearch 服务器版本兼容。如果不兼容,您需要升级客户端库或降级 Elasticsearch 服务器到一个兼容的版本。
  2. 升级 Elasticsearch 服务器或客户端库到一个共同支持的版本。可以在 Elasticsearch 的官方文档中找到关于不同版本之间的兼容性信息。
  3. 如果您不能升级,可以考虑使用较旧版本的客户端库,但这可能会引入安全问题和性能问题。

请确保在升级前备份数据,以防在升级过程中出现问题。

由于提问中包含的文档和PPT内容较多,并且涉及到具体的源代码和实现细节,我无法在这里提供完整的解决方案。但我可以提供一个概览和关键代码段的示例。

高校科研信息管理系统的核心功能可能包括:

  1. 科研项目管理:创建、修改、搜索和跟踪科研项目。
  2. 论文发表管理:管理学术论文,包括查新、审核和索引。
  3. 成果展示:展示研究成果,如专利、软件著作权等。
  4. 资源共享:学术资源共享,如参考文献、数据集等。
  5. 用户权限管理:基于角色的访问控制。

以下是一个简化的代码示例,展示如何在Spring Boot应用中集成Elasticsearch,并进行简单的文档搜索操作:




@RestController
public class SearchController {
 
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;
 
    @GetMapping("/search")
    public ResponseEntity<?> search(@RequestParam String query) {
        // 构建查询条件
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.multiMatchQuery(query, "title", "content"))
                .build();
 
        // 执行查询
        SearchHits<MyDocument> searchHits = elasticsearchRestTemplate.search(searchQuery, MyDocument.class);
 
        // 处理结果
        List<MyDocument> results = Arrays.asList(searchHits.getContent());
        return ResponseEntity.ok(results);
    }
}
 
// 假设MyDocument是一个映射Elasticsearch文档的实体类
@Document(indexName = "my_index")
public class MyDocument {
    @Id
    private String id;
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String title;
    @Field(type = FieldType.Text, analyzer = "ik_max_word")
    private String content;
 
    // 省略getter和setter方法
}

在这个例子中,我们定义了一个简单的搜索接口,用户可以通过传入查询字符串来搜索标题或内容中包含该查询字符串的文档。ElasticsearchRestTemplate用于与Elasticsearch集成,执行搜索操作,并将结果返回给用户。

请注意,这只是一个高度抽象的代码示例,实际的系统可能需要更复杂的用户权限控制、项目状态跟踪、论文审核流程等功能。源代码和完整文档需要根据具体项目需求进行设计和实现。

在ElasticSearch中,我们可以使用BM25来进行相关性评分,并结合嵌入模型(如transformers)来改善搜索结果。以下是一个简化的例子,展示如何在ElasticSearch中集成BM25和嵌入模型。

首先,你需要一个ElasticSearch集群,并确保你的文档包含两部分信息:基本信息和文本信息。




{
  "title": "文档标题",
  "content": "文档内容",
  "embedding": [0.1, 0.2, ...]  // 文档的嵌入向量
}

然后,你可以在ElasticSearch的设置中使用BM25,并使用嵌入模型的输出作为相关性评分的一部分。




PUT /my_index
{
  "settings": {
    "index": {
      "similarity": {
        "my_similarity": {
          "type": "BM25",
          "k1": 1.2,
          "b": 0.75
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "similarity": "my_similarity"
      },
      "content": {
        "type": "text",
        "similarity": "my_similarity"
      },
      "embedding": {
        "type": "dense_vector",
        "dims": 100  // 嵌入向量的维度
      }
    }
  }
}

在查询时,你可以结合BM25得分和嵌入向量得分:




GET /my_index/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "content": "查询内容"
        }
      },
      "functions": [
        {
          "script_score": {
            "script": {
              "source": "cosineSimilarity(params.query_vector, 'embedding') + params.bm25_score",
              "params": {
                "query_vector": [0.1, 0.2, ...]  // 查询的嵌入向量
              }
            }
          }
        }
      ],
      "boost_mode": "sum"
    }
  }
}

在这个例子中,我们定义了一个my_similarity的相似性评分,它使用了BM25公式。在查询时,我们使用了ElasticSearch的函数查询功能,结合了BM25得分和基于余弦相似度的嵌入向量得分。这样可以更好地结合传统搜索和深度学习的结果。

要使用npm命令删除项目中的node_modules文件夹,您可以在项目的根目录中执行以下命令:




npm install --only=dev
npm prune

这将先安装只作为开发依赖的包,然后删除那些不在package.json中列出的任何包。这样做的目的是为了最大程度地减小node_modules文件夹的大小,因为它只包含开发依赖项。

如果您只是想直接删除node_modules文件夹,而不考虑开发依赖,可以使用操作系统的文件删除命令。在Unix-like系统(如Linux和macOS)上,您可以使用:




rm -rf node_modules

在Windows系统上,您可以使用:




rmdir /s /q node_modules

请注意,直接删除node_modules可能会导致某些依赖不完整,因此通常建议使用npm命令来管理它的清理。

在Elasticsearch中,全模糊匹配通常通过使用match_phrase_prefix查询来实现,但它主要用于短语或词根匹配。如果你需要进行复杂的全模糊匹配,可以考虑以下几种方法:

  1. 使用match_phrase_prefix查询:适用于匹配短语的开始部分。
  2. 使用wildcard查询:可以通过通配符实现更复杂的匹配,但性能较差。
  3. 使用ngram分析器:在索引时将文本分割成短语,以支持复杂的全模糊匹配。

以下是使用ngram分析器实现全模糊匹配的示例配置和查询:

首先,在创建索引时定义一个ngram分析器:




{
  "settings": {
    "analysis": {
      "tokenizer": {
        "my_ngram_tokenizer": {
          "type": "ngram",
          "min_gram": 2,
          "max_gram": 10
        }
      },
      "analyzer": {
        "my_ngram_analyzer": {
          "tokenizer": "my_ngram_tokenizer"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "text": {
        "type": "text",
        "analyzer": "my_ngram_analyzer"
      }
    }
  }
}

然后,使用match查询进行全模糊匹配:




{
  "query": {
    "match": {
      "text": "your search term"
    }
  }
}

这样配置后,当你搜索"your search term"时,Elasticsearch会将搜索词分解成n-grams,并查找包含这些n-grams的文档。这允许你执行全模糊匹配,即不区分大小写和匹配短语的开始部分。

Elasticsearch的Update By Query API允许你根据一个查询来更新文档。这个API可以用来执行全量或增量的更新,也可以用来删除文档。

以下是一个使用Update By Query的Python代码示例,使用Elasticsearch的官方Python客户端:




from elasticsearch import Elasticsearch
from elasticsearch.helpers import bulk
 
# 初始化Elasticsearch客户端
es = Elasticsearch("http://localhost:9200")
 
# 定义更新操作
def update_document(es, index, query, script):
    update_query = {
        "query": query,
        "script": script
    }
    es.update_by_query(index=index, body=update_query)
 
# 使用示例
index_name = 'your_index'
query = {
    "match": {
        "your_field": "your_value"
    }
}
script = {
    "source": "ctx._source.your_field = params.new_value",
    "params": {
        "new_value": "new_value"
    }
}
 
update_document(es, index_name, query, script)

在这个示例中,我们定义了一个update_document函数,它接受Elasticsearch客户端、索引名、查询和脚本作为参数。然后我们构建了一个update_by_query请求的字典,其中包含了我们的查询和脚本,最后我们调用es.update_by_query方法来执行更新。

请注意,你需要根据你的Elasticsearch服务器的实际情况调整代码中的Elasticsearch服务器地址和其他参数。

在移动端中,Graphics API是用于渲染图形的接口。主要有以下几种:Vulkan、OpenGL ES、DirectX。

  1. Vulkan:

    Vulkan是一个由Khronos组织开发的图形API,主要用于跨平台的高性能图形渲染。它专为移动平台和桌面平台设计,支持多核心处理器的并行处理能力,同时还有高效的内存管理和高速的渲染能力。

Unity3D支持Vulkan API,可以通过Player Settings设置。




#if UNITY_ANDROID && !UNITY_EDITOR
    GraphicsDeviceType[] devices = new GraphicsDeviceType[] {
        GraphicsDeviceType.Vulkan
    };
    QualitySettings.SetGraphicsAPIs(devices);
#endif
  1. OpenGL ES:

    OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL三维图形API的子集,主要用于嵌入式设备,如手机和平板电脑。Unity3D支持OpenGL ES作为底层图形API。




#if UNITY_IOS
    GraphicsDeviceType[] devices = new GraphicsDeviceType[] {
        GraphicsDeviceType.OpenGLES3,
        GraphicsDeviceType.OpenGLES2
    };
    QualitySettings.SetGraphicsAPIs(devices);
#endif
  1. DirectX:

    DirectX是微软开发的一套由软件和硬件接口组成的游戏音视频开发包,主要用于Windows平台的游戏和应用程序。

Unity3D支持DirectX 11和DirectX 12,但不直接支持DirectX 10。




#if UNITY_WINRT && !UNITY_EDITOR
    GraphicsDeviceType[] devices = new GraphicsDeviceType[] {
        GraphicsDeviceType.Direct3D11,
        GraphicsDeviceType.Direct3D12
    };
    QualitySettings.SetGraphicsAPIs(devices);
#endif

注意:以上代码只是设置图形API,并不会真正改变Unity3D的渲染路径,具体渲染路径由Unity3D根据项目设置和硬件条件自动选择。

在ElasticSearch中,得分是用来评估查询结果与用户搜索query的匹配程度的。得分的计算依赖于特定的相关性算法,这通常涉及到查询中使用的词项以及这些词项在文档中出现的频率和位置。

ElasticSearch中的相关性算法是可以配置的,但默认情况下使用的是Okapi BM25算法。

以下是一个简单的查询示例,它演示了如何在ElasticSearch中执行查询并获取文档及其相关得分:




GET /_search
{
  "query": {
    "match": {
      "message": "Elasticsearch"
    }
  }
}

在返回的结果中,每个文档都会有一个_score字段,这个字段就是该文档的得分。

如果你想要调整相关性算法的参数,可以在ElasticSearch配置中设置index.similarity。但这通常不是普通用户会进行的操作,而是更专业的优化步骤。

如果你想要了解得分是如何计算的,你可以使用explain参数进行查询,这将返回得分的详细计算过程:




GET /_search?explain
{
  "query": {
    "match": {
      "message": "Elasticsearch"
    }
  }
}

在返回的结果中,每个文档都会有一个_explanation字段,这个字段详细解释了为什么该文档得到了特定的得分。

解释:

在Python中,multiprocessing模块用于创建子进程。进程间通信(IPC)通常需要序列化和反序列化数据,而_thread.lock对象不是可序列化的,因为它是一个与线程相关的锁对象,不能被传递到另一个进程中。

解决方法:

  1. 避免在multiprocessing中使用_thread.lock对象。
  2. 如果需要在多个进程间协调,可以使用multiprocessing模块提供的锁对象,如multiprocessing.Lock
  3. 如果必须使用_thread.lock,可以考虑不使用multiprocessing的进程池或队列,改用线程。

示例代码:




import threading
 
# 使用 threading.Lock 而不是 _thread.lock
lock = threading.Lock()
 
# 在多线程环境中安全地使用锁
with lock:
    # 执行需要互斥的代码
    pass

如果确实需要进程间同步,则使用multiprocessing模块中的进程锁:




from multiprocessing import Process, Lock
 
def func(lock):
    with lock:
        # 执行需要互斥的代码
        pass
 
if __name__ == '__main__':
    lock = Lock()
    p = Process(target=func, args=(lock,))
    p.start()
    p.join()